第四章:数组
-
概述:一个定长的容器
-
数组元素:数组中的每一项就是数组元素
-
-
数组的创建和定义
// 数组的声明 int[] arr1; int arr2[]; // 数组的创建 /* * 动态创建:在创建数组的同时JVM对数组元素赋默认值 *静态创建: 在创建数组的同时给数组元素赋自定义的值 * */ // 动态创建:在创建数组的同时JVM对数组元素赋默认值 /** * 默认值:整型:0 double:0.0 float:0.0f char:\u0000 boolean:false 引用数据类型:null */ int[] arr3=new int[3]; // 以字符串的形式输入数据数据Arrays.toString(数组引用) System.out.println(Arrays.toString(arr3));//[0, 0, 0] String[] arr4=new String[4]; System.out.println(Arrays.toString(arr4));//[null, null, null, null] // 静态创建: 在创建数组的同时给数组元素赋自定义的值,数组的长度由赋值的元素个数决定 // 方式一: int[] arr5=new int[] {123,456,789}; System.out.println(Arrays.toString(arr5));//[123, 456, 789] // 方式二: int[] arr6 = {456,123,1}; System.out.println(Arrays.toString(arr6));//[456, 123, 1] // 数组的访问:通过索引访问数组元素 System.out.println(arr6[0]);//456 // 经常出现的bug:索引越界异常 ArrayIndexOutOfBoundsException // System.out.println(arr6[3]); // 数组的长度 System.out.println(arr6.length);//3
-
数组的特点:
-
数组是定长的,数组在创建的同时必须指定数组的长度(数组元素的个数)
-
数组既可以存放基本数据类型数据也可以存放引用数据类型数据
-
数组是一种数据结构,顺序存储:在逻辑地址上连续的两个元素在内存地址上也连续
-
数组是有顺序有索引的,索引从0开始最大值为length-1
-
访问速度很快
-
-
数组是引用数据类型,引用数据类型数据存放在堆区(堆区一般存放引用数据类型的值,所以堆区比栈区大得多)
-
-
注意:
-
数组的数据类型一但定义,数组元素的数据类型与数组的类型保持一致
-
-
数组的内存分析
-
数组是引用数据类型,引用数据类型数据存放在堆区
-
引用数据类型数据存放在堆区其地址引用存放在栈区
// arr1:引用:在java中就是地址的意思,通过引用可以找打对应的对象地址 // new:内存空间分配符,程序遇见new就会在堆区中开配内存空间存放对象数据 int[] arr1=new int[3]; System.out.println(Arrays.toString(arr1));//[0, 0, 0] System.out.println(arr1[0]); System.out.println(arr1);//@7852e922 // 数组元素的赋值 arr1[0]=90; System.out.println(Arrays.toString(arr1));//[90, 0, 0] // 只有new会在堆区中创建对象 int[] arr2=new int[] {1,2,3}; // 编译器在编译时会自动加上 new int[]{4,5,6}; int[] arr3= {4,5,6}; System.out.println(arr3);//@4e25154f System.out.println("-------------------------------"); // 数组的遍历 for(int i=0;i<arr3.length;i++) { System.out.println(arr3[i]); } System.out.println("-------------------------------"); // 专门遍历容器的方式:foreach加强for循环 /** * for(数组元素类型 变量:容器){ * * } * */ for(int i:arr3) { System.out.println(i); } // 求数组最大值、最小值和平均值。 int a[] = {1,-12,31}; int max=0; int sum=0; for(int i=0;i<a.length;i++) { sum+=a[i]; if(max<a[i]) { max=a[i]; } } System.out.println("最大值:"+max); System.out.println("平均值:"+(double)sum/a.length); // 空指针异常NullPointerException int[] aa=null; // System.out.println(aa.length);
-
-
数组的排序和查找
-
冒泡排序
// 冒泡排序 public static void main(String[] args) { int[] arr1= {89,45,12,99,78,65}; // 将arr1升序排序 for(int j=1;j<arr1.length;j++) { for(int i=0;i<arr1.length-j;i++) { if(arr1[i+1]<arr1[i]) { int temp=arr1[i]; arr1[i]=arr1[i+1]; arr1[i+1]=temp; } } // System.out.println("第"+(j+1)+"查找:"+Arrays.toString(arr1)); } System.out.println("升序后的结果:"+Arrays.toString(arr1));// [12, 45, 65, 78, 89, 99] // 将arr1降序排序 for(int j=1;j<arr1.length;j++) { for(int i=0;i<arr1.length-j;i++) { if(arr1[i+1]>arr1[i]) { int temp=arr1[i]; arr1[i]=arr1[i+1]; arr1[i+1]=temp; } } // System.out.println("第"+(j+1)+"查找:"+Arrays.toString(arr1)); } System.out.println("降序后的结果:"+Arrays.toString(arr1));//[99, 89, 78, 65, 45, 12] }
-
二分查找
二分查找的前提是需要查找的数组必须是已排序的,这里实现默认前提为升序。查找时将数组分为三部分,依次是中值(所谓的中值就是数组中间位置的那个值)前,中值,中值后;将要查找的值和数组中的值进行比较,若小于中值则在中值前面找,若大于中值则在中值后面找,等于中值时直接返回。从描述上就可以看出这个算法适合用循环来实现。
// 二分查找:前提是已经拍好序的数列 int[] sort = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; int key=6;//锁定查找的数值 int index=-1;//查找到的索引位置 int l=0;//最左边索引位置 int h=sort.length-1;//最右边索引位置 while(l<=h) { int min=(l+h)/2;//中间索引位置 if(sort[min]==key) { //锁定查找数据的索引位置 index=min; break; }else if(key<sort[min]) { //key小于中间值 h=min-1; }else { //key大于中间值 l=min+1; } } // 没有找到对应数值 if(index==-1) { System.out.println("没找到"); }else { System.out.println("找到的位置为:"+index); } }
-
数组的操作
-
数组的sort()方法排序和数组的复制
// 数组的sort()排序:默认升序排序,如果想让降序排序需要自定义排序规则(后续讲解) int[] arr1= {89,45,12,99,78,65}; Arrays.sort(arr1); System.out.println(Arrays.toString(arr1));//[12, 45, 65, 78, 89, 99] // 数组的复制 /** * 将原数组索引位置开始的所有元素替换掉目标数组从开始索引位置length个元素 * src:原数组 * srcPos:原数组的开始索引位置 * dest:目标数组 * destPos:目标数组开始索引位置 * length:替换的元素个数 */ int[] arraysrc= {7,8,9}; int[] arraydest= {1,2,3,4,5,6,99}; System.arraycopy(arraysrc, 0, arraydest, 2, 3); System.out.println(Arrays.toString(arraydest));
-
-
二维数组
-
java中没有真正的二维数组,只有数组中再存放数组
// 二维数组声明和创建 int[][] arr1; int arr2[][]; int[] arr3[]; // 二维数组的创建 // 动态创建 /** * 3:3行--数组的长度,可以理解为一维数组元素的个数,说明该一维数组中可以存放三个一维数组 * 注意:该一维数组的元素必须是一维数组 */ int[][] a1=new int[3][]; System.out.println(Arrays.toString(a1));//[null, null, null] System.out.println(a1); /** * 3:行 * 4:每一个元素数组的长度为4 */ int[][] a2=new int[3][4]; System.out.println(a2);//[I@4e25154f System.out.println(Arrays.toString(a2));//[[I@70dea4e, [I@5c647e05, [I@33909752] // 静态创建 int[][] a3= {{2,3},{4,5,6},{7,8,9,10}}; System.out.println(Arrays.toString(a3));//[[I@7852e922, [I@4e25154f, [I@70dea4e] // 二维数组的访问 System.out.println(a2[0]);//@70dea4e System.out.println(Arrays.toString(a2[0]));//[0, 0, 0, 0] System.out.println(Arrays.toString(a3[0]));//[2, 3] // int[] aa; // aa= {23,45}; 编译报错 // aa=new int[] {23,45}; // 二维数组的赋值 a3[0]= new int[]{23,45}; System.out.println(Arrays.toString(a3[0]));//[23, 45] a3[0][0]=77; System.out.println(Arrays.toString(a3[0]));//[77, 45] System.out.println("---------------------------------"); // 二维数组的遍历 for(int i=0;i<a3.length;i++) { System.out.println(Arrays.toString(a3[i])); } System.out.println("-------------=--------------------"); for(int i=0;i<a3.length;i++) { for(int j=0;j<a3[i].length;j++) { System.out.println(a3[i][j]); } } // 定义一个3行3列的二维数组,并快速为数组中所有的元素赋值1~9 int[][] a4=new int[3][3]; int num=1; for(int i=0;i<a4.length;i++) { for(int j=0;j<a4[i].length;j++) { a4[i][j]=num; num++; } } for(int i=0;i<a4.length;i++) { System.out.println(Arrays.toString(a4[i])); }
-
-