1.数组(Array)
数组是多个相同类型数据按一定顺序排列的集合,并使用一个名字命名,并通过编号的方式对这些数据进行统一管理
2.数组的常见概念
1)数组名
2)下标(或索引、角标)
3)元素
4)数组的长度
3.数组的特点:
1)数组是有序排列的。
2)数组属于应用数据类型的变量而数组中的元素可以是任何数据类型,包括基本数据类型和引用数据类型。
3)创建数组对象会在内存中开辟一整块连续的空间,而数组名中引用的是这块连续空间的首地址。
4)数组的长度一旦确定,就不能修改。
4.数组的分类
1)按照维度:一维数组、二维数组、三维数组、…
2)按照元素的数据类型分:基本数据类型元素的数组、引用数据类型元素的数组(即对象数组)
5. 一维数组的使用
① 一维数组的声明和初始化
1>静态初始化:数组的初始化和数组元素的赋值同时进行**
数据类型[ ] 数组名(=null); //声明数组
(数据类型 数组名[] (=null)这种也可以)
数组名 = new 数据类型[ ]{数组中的元素0,元素1,……}; //分配内存给数组,new的意思是创建一个储存空间
或
据类型[ ] 数组名 = new 数据类型[]{数组中的元素0,元素1,……};
例
int[] ids; //声明
ids = new int[]{1001,1002,1003,1004}; //分配内存给数组1001,1002,1003,1004
//或
int[] ids = new int[]{1001,1002,1003,1004};
2>动态初始化:数组的初始化数组元素的赋值分开进行
数据类型[ ] 数组名(=null);
数组名 = new 数据类型[ 数组长度(个数)]
或
数据类型[ ] 数组名 = new 数据类型[数组长度(个数)]
例
String[] names;
names = new String[5];
//或
String[ ] names = new String[5];
② 如何调用数组的指定位置的元素
调用数组的指定位置的元素:通过角标的方式调用。
数组的角标(或索引)从0开始的,到数组的长度-1结束。
例
names[0] = "王铭";
③ 如何获取数组的长度
每个数组都有一个属性length指明它的长度,例如:a.length指明数组a的长度(元素个数)
例
int[] arr = new int[]{1,2,3};
④ 如何遍历数组
遍历数组{1001,1002,1003,1004}
int[] ids = new int[]{1001,1002,1003,1004};
for(int i = 0;i < ids.length;i++){
System.out.println(ids[i]);
}
⑤ 数组元素的默认初始化值
- 数组元素是整型(int、long、short、byte):0
- 数组元素是浮点型(float、double):0.0
- 数组元素是char型:0或’\u0000’,而非’0’
- 数组元素是boolean型:false
- 数组元素是引用数据类型:null
⑥ 数组的内存解析 :见B站 尚硅谷143、144集
例
int[] arr = new int[]{1,2,3};
上述代码中,局部变量arr存于栈,new出来的变量1,2,3,存于堆,栈空间的arr存储堆空间中连续数组1,2,3的首地址值。如下图。0x34ab是数组1,2,3的首地址值,通过arr中存储的地址找到数组。
栈空间 堆空间
6.二维数组的使用
理解:对于二维数组的理解,我们可以看成是一维数组array1又作为另一个一维数组array2的元素而存在。其实,从数组底层的运行机制来看,其实没有多维数组。
① 二维数组的声明和初始化
1>静态初始化
int[][]arr1 = new int[][]{{1,2,3},{4,5},{6,7,8}}; // 这里定义的数组是1、2、3/4、5/6、7、8、0
2>动态初始化
int [ ][ ]arr1 = new int[3][4]; //new int [ ][ ]中第一个[ ]代表行数,第二个[ ]代表列数。
② 如何调用数组的指定位置的元素
和一维数组调用一样,例:
int[] arr4[] = new int[][]{{1,2,3},{4,5},{6,7,8}};
int[] arr5[] = {{1,2,3},{4,57,9},{6,7,8}};
System.out.println(arr4[0][1]); //输出2
System.out.println(arr5[1][0]); //输出4
③ 如何获取数组的长度
System.out.println(arr4.length); //3 arr4的长度是行的长度
System.out.println(arr4[0].length); //3 arr4[0]表示第零行的长度,既{{1,2,3}}的长度
System.out.println(arr4[1].length); //2 arr4[1]表示第一行的长度,既{{4,5}}的长度
④ 如何遍历数组
for(int i = 0;i < arr4.length;i++){
for(int j = 0;j < arr4[i].length;j++){
System.out.print(arr4[i][j] + " ");
}
System.out.println(); //换行
}
/*编译结果:
1 2 3
4 5 9 10
6 7 8 */
⑤ 数组元素的默认初始化值
(规定:二维数组分为外层数组的元素,内层数组的元素
int[ ][ ] arr = new int[4][3];
外层元素:arr[0],arr[1]等
内层元素:arr[0][0],arr[1][2]等)
针对于初始化方式一:
比如:int[][] arr = new int[4][3];
外层元素的初始化值为:内层数组的地址值
内层元素的初始化值为:与一维数组初始化情况相同
针对于初始化方式二:
比如:int[][] arr = new int[4][];*
外层元素的初始化值为:null
内层元素的初始化值为:不能调用,否则报错。
⑥ 数组的内存解析
见尚硅谷Java基础 ArrayTest3.java
7.数组中涉及到的常用算法
①数组的复制
注意: 复制array1数组给array2时不能直接用 array2 = array1 ; array1是数组的首地址值,直接这样的话,只是把array1存储的首地址值赋给array2了,如图
应该用如下代码:
int[] array1, array2;
array2 = new int[array1.length];
for(int i = 0;i < array2.length;i++){
array2[i] = array1[i];
}
内存解析如图
②二分法查找算法(前提:所要查找的数组必须有序。)
例如,查找一有序数组中元素为18的位置时,先从2到28的中间位置查找,如果查找元素大于中间位置的元素,则从后半段的中间位置开始查找,以此类推,直到找到,如图所示
以上方法为二分法图解
例题 查找数组arr3中元素256的位置
int[] arr3= newint[]{-99,-54,-2,0,2,33,43,256,999};
booleanisFlag= true;
intnumber= 256;
int head= 0; //首索引位置
int end= arr3.length-1; //尾索引位置
while(head<= end){
int middle= (head+ end) / 2;
if(arr3[middle] == number){
System.out.println("找到指定的元素,索引为:"+ middle);
isFlag= false;
break;
}
else if(arr3[middle] > number){
end= middle-1;
}
else{ //arr3[middle] < number时
head= middle+ 1;
}
}
if(isFlag){
System.out.println("未找打指定的元素");
}
③排序算法
排序算法分类:内部排序和外部排序。
内部排序:整个排序过程不需要借助于外部存储器(如磁盘等),所有排序 操作都在内存中完成。
外部排序:参与排序的数据非常多,数据量非常大,计算机无法把整个排序过程放在内存中完成,必须借助于外部存储器(如磁盘)。外部排序最常见的是多路归并排序。可以认为外部排序是由多次内部排序组成。
1>冒泡排序
a.比较相邻的元素。如果第一个比第二个大(升序),就交换他们两个。
b.对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。
c.针对所有的元素重复以上的步骤,除了最后一个。
d.持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较为止。
例 用冒泡排序对43,32,76,-98,0,64,33,-21,32,99进行排序
int[] arr = new int[]{43,32,76,-98,0,64,33,-21,32,99};
//冒泡排序
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;
}
}
}
2>快速排序
a.从数列中挑出一个元素,称为"基准"(pivot),
b. 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区结束之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。
c. 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。
d. 递归的最底部情形,是数列的大小是零或一,也就是永远都已经被排序好了。虽然一直递归下去,但是这个算法总会结束,因为在每次的迭代(iteration)中,它至少会把一个元素摆到它最后的位置去。
7.数组arrays工具类使用
java.util.Arrays:操作数组的工具类,里面定义了很多操作数组的方法,常见方法:
①boolean equals(int[] a,int[] b):判断两个数组是否相等。
int[] arr1 = new int[]{1,2,3,4};
int[] arr2 = new int[]{1,3,2,4};
boolean isEquals = Arrays.equals(arr1, arr2);
System.out.println(isEquals);
②String toString(int[] a):输出数组信息。
System.out.println(Arrays.toString(arr1));
③void fill(int[] a,int val):将指定值填充到数组之中。
Arrays.fill(arr1,10);
System.out.println(Arrays.toString(arr1));
④void sort(int[] a):对数组进行排序。
Arrays.sort(arr2);
System.out.println(Arrays.toString(arr2));