一、数组的排序(冒泡排序)
原理:
从下标"0"开始,相邻两个元素依次进行比较,每次找出最大的往后移动。
规律:N个数字来排队,两两相比小靠前,外层循环N-1,内层循环N-1-i。
案例:对一组数组进行排队
javapublic class Test{ public static void main(String[] args){ int[] arr={5,6,2,7,8,3,1,9}; for(int i=0;i<arr.length-1;i++){ for(int j=0;j<arr.length-1-i;j++){ if(arr[j]>arr[j+1]){ int temp=arr[j]; arr[j]=arr[j+1]; arr[j+1]=temp; } } } for(int element:arr){ System.out.println(element); } } }
ps:排序只需要了解熟悉就行,因为在平常的Java开发中有专门的的工具类Arrays,所以排序一般只有在面试的时候可能会用到。
二、数组的查找
1.线性查找
线性查找就是用for循环进行遍历。
案例:
javaimport java.util.Scanner; public class Test{ public static void main(String[] args){ int[] arr={5,6,2,7,8,3,1,9}; Scanner scan=new Scanner(System.in); System.out.println("请输入需要查询的元素:"); int num=scan.nextInt(); for(int i=0;i<arr.length;i++){ if(num==arr[i]){ System.out.println("你查询的元素的下标为:"+i); } } } }
缺点:由于它是从首位开始依次进行查找的所以当数组中的元素过多是会影响查询的速度。
2.二分法/二叉查找
二分法是先将数组进行排序,然后确定三个下标:首位(start),最后一位(end),中间一位((start+end)/2=mid)ps:如果计算出现小数会自动省略,当中间位元素大于需查询的元素:end=mid-1,反之start=mid+1。
案例:
javaimport java.util.Arrays; import java.util.Scanner; public class Test{ public static void main(String[] args){ int[] arr={5,6,2,7,8,3,1,9}; Arrays.sort(arr);//排序 Scanner scan=new Scanner(System.in); System.out.println("请输入需要查询的元素:"); int num=scan.nextInt(); int start=0; int end=arr.length-1; while(start<=end){ int mid =(start+end)/2; if(num< arr[mid]){ end=mid-1; }else if(num>arr[mid]){ start=mid+1; }else{ System.out.println("你查询的元素的下标为:"+mid); break; } } } }
三、数组扩展
1.数组的复制
浅表赋值
案例:
javapublic class Test04{ public static void main(String[] args){ //原数组 String[] arr = {"张三","李四","王五"}; //新数组 String[] newArr = arr; //修改原数组 arr[1] = "赵六"; //遍历新数组 for(String element : newArr){ System.out.println(element); } } }
缺点:修改原数组,新数组中的数据也会发生改变
原理:
深表赋值
案例:
javapublic class Test05{ public static void main(String[] args){ //原数组 String[] arr = {"张三","李四","王五"}; //新数组 String[] newArr = new String[arr.length]; //将原数组下标的元素赋值给新数组 for(int i = 0;i<arr.length;i++){ newArr[i] = arr[i]; } //修改原数组 arr[1] = "赵六"; //遍历新数组 for(String element : newArr){ System.out.println(element); } } }
原理:
2.数组的扩容
案例:
javapublic class Test06{ public static void main(String[] args){ //原数组 String[] arr = {"张三","李四","王五"}; //计算新容量 int oldCapacity = arr.length;//3 int newCapacity = oldCapacity + (oldCapacity>>1);//4 //新数组 String[] newArr = new String[newCapacity]; //将原数组下标的元素赋值给新数组 for(int i = 0;i<arr.length;i++){ newArr[i] = arr[i]; } //将新数组的地址赋值给原数组 arr = newArr; //遍历原数组 for(String element : arr){ System.out.println(element); } } }
3.数组的删除
方法一案例:
javapublic class Test{ public static void main(String[] args){ //原数组 String[] arr = {"张三","李四","王五","赵六"}; //新数组 String[] newArr = new String[arr.length-1];//3 - [null,null,null] int index = 0; for(String element : arr){ if(!element.equals("李四")){ newArr[index++] = element; } } //将新数组的地址赋值给原数组 arr = newArr; //遍历原数组 for(String element : arr){ System.out.println(element); } } }
缺点:数组作为容器,是存储数据的,这样的删除会让容器越变越小
方法二
javapublic class Test{ public static void main(String[] args){ //原数组 String[] arr = {"张三","李四","王五","赵六"}; //将删除元素后一位的数据全部都往前移 for(int i = 1;i<arr.length-1;i++){ arr[i] = arr[i+1]; } //将最后一位数据赋值为null arr[arr.length-1] = null; //遍历原数组 for(String element : arr){ System.out.println(element); } } }
4.数组作为方法的参数和返回值
案例:设计一个方法,传入int类型的数组,返回最大值和最小值
javapublic class Test{ public static void main(String[] args){ int[] arr = {5,78,55,26,23,51,32}; int[] newArr = getMaxAndMin(arr); System.out.println("最大值为:" + newArr[0]); System.out.println("最小值为:" + newArr[1]); } public static int[] getMaxAndMin(int[] arr){ int max = arr[0]; int min = arr[0]; for(int i = 1;i<arr.length;i++){ if(max < arr[i]){ max = arr[i]; } if(min > arr[i]){ min = arr[i]; } } int[] maxAndMin = {max,min}; return maxAndMin; } }
5.可变参数
案例:设计一个方法,传入n个int类型的值,返回最大值
javapublic class Test{ public static void main(String[] args){ int max = getMax(1,2,3,4,5,6,7);//将实参作为数组的元素传入 System.out.println(max); } //int... arr -- 可变参数,实际上就是数组 public static int getMax(int... arr){ if(arr.length == 0){//意味着实参没有传任何数据 return -1; } int max = arr[0]; for(int i = 1;i<arr.length;i++){ if(max < arr[i]){ max = arr[i]; } } return max; } }
注意:可变参数后不能接其他参数
四、Arrays工具类
理解:Arrays是Java给我们提供的专门用于操作数组的工具类
概念:
- 工具类 -- 该类中的方法都是静态的,直接使用类名调用
- API ----- Java提供类的说明书
案例:
javaimport java.util.Arrays; public class Test{ public static void main(String[] args){ int[] arr = {5,72,9,4,21,1,6,3,81}; //排序 - 1,3,4,5,6,9,21,72,81 Arrays.sort(arr); //查找 //返回值规则:搜索键的索引,如果它包含在数组中; 否则, (-(insertion point) - 1) //返回值规则:如果元素包含在数组中,返回下标;否则,(-(插入点) - 1) int index = Arrays.binarySearch(arr,30); System.out.println("查找到元素的下标为:" + index); //拷贝数组 int[] newArr1 = Arrays.copyOf(arr,15); //拷贝数组区间 int[] newArr2 = Arrays.copyOfRange(newArr1,2,11);//(目标数组,开始下标-包含,结束下标-排他) //替换所有元素 Arrays.fill(newArr2,888); //替换区间元素 Arrays.fill(newArr2,2,4,666);//(目标数组,开始下标-包含,结束下标-排他,替换元素) //将数组转换为字符串 String str = Arrays.toString(newArr2); System.out.println(str); } }
五、二维数组
理解:二维数组包含了多个一维数组
数组的声明:
- 数据类型[][] 数组名;00
- 数据类型 数组名[][];
静态初始化
案例:
javapublic class Test{ public static void main(String[] args){ //静态初始化1 //String[][] names = new String[][]{{"小明","小红","小绿"},{"张三","李四","王五","赵六"}}; //静态初始化2 //String[][] names; //names = new String[][]{{"小明","小红","小绿"},{"张三","李四","王五","赵六"}}; //静态初始化3 String[][] names = {{"小明","小红","小绿"},{"张三","李四","王五","赵六"}}; //设置指定下标上的元素 names[0][1] = "星星"; //获取指定下标上的元素 String str = names[0][1]; System.out.println("获取指定下标上的元素:" + str); //获取长度 System.out.println("获取二维数组中一维数组的长度:" + names.length);//2 System.out.println("获取二维数组中第一个一维数组元素的长度:" + names[0].length);//3 System.out.println("获取二维数组中第二个一维数组元素的长度:" + names[1].length);//4 System.out.println("------------------------------------"); //遍历思路:循环遍历出一维数组,再循环遍历一维数组的元素 //遍历数组 -- for循环 for(int i = 0;i<names.length;i++){ for(int j = 0;j<names[i].length;j++){ System.out.println(names[i][j]); } } System.out.println("------------------------------------"); for(String[] ss:names){ for(String element:ss){ System.out.println(element); } } } }
案例1:动态初始化
javapublic class Test{ public static void main(String[] args){ //动态初始化1 //String[][] names = new String[2][3];//2表示2个一维数组,3表示每个一维数组有3个元素 //动态初始化2 String[][] names; names = new String[2][3];//2表示2个一维数组,3表示每个一维数组有3个元素 //设置指定下标上的元素 names[0][1] = "小红"; //获取指定下标上的元素 String str = names[0][1]; System.out.println("获取指定下标上的元素:" + str); //获取长度 System.out.println("获取二维数组中一维数组的长度:" + names.length);//2 System.out.println("获取二维数组中第一个一维数组元素的长度:" + names[0].length);//3 System.out.println("获取二维数组中第二个一维数组元素的长度:" + names[1].length);//4 //遍历思路:循环遍历出一维数组,再循环遍历一维数组的元素 //遍历数组 -- for循环 for(int i = 0;i<names.length;i++){ for(int j = 0;j<names[i].length;j++){ System.out.println(names[i][j]); } } for(String[] ss:names){ for(String element:ss){ System.out.println(element); } } } }
案例2:使用动态初始化声明二维数组,二维数组中有两个一维数组,第一个一维数组有3个元素 ,第二个一维数组有4个元素
javapublic class Test{ public static void main(String[] args){ String[][] names = new String[2][]; String[] s1 = {"aaa","bbb","ccc"}; String[] s2 = {"ddd","eee","fff"}; names[0] = s1; names[1] = s2; for(String[] ss:names){ for(String element:ss){ System.out.println(element); } } } }
动态初始化声明二维数组,二维数组中有两个一维数组,第一个一维数组有3个元素 ,第二个一维数组有4个元素
javapublic class Test{ public static void main(String[] args){ String[][] names = new String[2][]; String[] s1 = {"aaa","bbb","ccc"}; String[] s2 = {"ddd","eee","fff"}; names[0] = s1; names[1] = s2; for(String[] ss:names){ for(String element:ss){ System.out.println(element); } } } }
底层原理: