数组
概念
是计算机内存中的一块连续性存储空间,特点为可以同时存放多个相同数据类型的值
创建
- 先声明,后指明长度
数据类型[] 数组名;
数组名=new 数据类型[长度];
数据类型[] 数组名;
数据类型 []数组名;
数据类型 数组名[];
- 创建的时候必须指明长度,方便内存分配空间
- 长度必须为正整型
- 声明的同时直接指明长度
数据类型[] 数组名=new 数据类型[长度];
- 创建的同时直接赋值
数据类型[] 数组名=new 数据类型[]{值1,值2};
- 数组长度由值的个数决定
- 中括号指明长度不可与大括号赋值同时存在
- 创建的同时直接赋值
数据类型[] 数组名={值1,值2,..};
- 无法先声明后大括号直接赋值
//先声明
int[] arr5;
//后直接大括号赋值
arr5 = new int[]{10, 20, 30};
//arr5 ={10, 20, 30}; 错误
//先声明,后指明长度
int[] arr1;
arr1 = new int[3];
//声明的同时直接指明长度
int[] arr2 = new int[3];
//创建的同时直接赋值
int arr3[] = new int[]{20, 23, 21};
int[] arr4 = {20, 21, 22};
下标
-
必须通过下标操作数组元素
-
从0开始,至数组长度前一位结束
-
使用:
取值: 数组名[下标]
赋值: 数组名[下标]=值;
- 当下标使用超出界限时,运行时会报出数组下标越界异常
java.lang.ArrayIndexOutOfBoundsException
- 可以通过
数组名.length
获取数组长度
遍历
for(int i=0;i<数组名.length;i++){
//数组名[i]就代表当前正在被遍历的元素
}
//创建一个长度为3的数组
int[] arr = new int[3];
//赋值
arr[0] = 10;
arr[1] = 20;
arr[2] = 30;
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
数组高级
深入数组底层
- 属于引用类型
- 内存存放:
- 引用中存放着对应的堆地址
- 程序员在操作时必须先进入栈,再由栈中存储的堆地址进入堆操作数据
- 引用类型之间相互赋值转递是堆地址
int[] arr1 = {10, 20, 30, 40, 50};
int[] arr2 = arr1;
arr2[0] = 66;
int[] arr3 = arr1;
arr3 = new int[]{11, 22, 33};
System.out.print("arr1: ");
for (int i = 0; i < arr1.length; i++) {
System.out.print(arr1[i]+"\t");
}// 66 20 30 40 50
System.out.println();
System.out.print("arr2: ");
for (int i = 0; i < arr2.length; i++) {
System.out.print(arr2[i]+"\t");
}// 66 20 30 40 50
System.out.println();
System.out.print("arr3: ");
for (int i = 0; i < arr3.length; i++) {
System.out.print(arr3[i]+"\t");
}//11 22 33
逢new必开:只要执行到new关键字,就一定会有新的堆空间被开辟创建
- 数组存在默认值,作用为方便内存分配空间
默认值:编译器赋予
初始值:程序员第一次手动赋值
int: 0
double : 0.0
String : null (所有引用类型都是null)
boolean : false
数组扩容
步骤
- 创建一个长度更大的数组,推荐扩容两倍
- 将原数组的数据复制到新数组中
- 将原数组的地址转换为新数组地址
for循环实现
int[] a = {10, 20, 30, 40, 50};
//创建一个长度为2倍的数组
int[] newA = new int[a.length * 2];//{0, 0, 0, 0, 0,0,0,0,0,0}
//{10,20,30,40,50,0,0,0,0,0}
//将原数组数据复制到新数组中
for (int i = 0; i < a.length; i++) {
newA[i]=a[i];//newA[1]=a[1]
}
//将原数组的地址转换为新数组地址
a = newA;
System.arraycopy
- System.arraycopy(原数组名,原数组复制起始下标,新数组名,新数组存放起始下标,复制长度)
int[] a = {10, 20, 30, 40, 50};
//创建一个长度为2倍的数组
int[] newA = new int[a.length * 2];//{0, 0, 0, 0, 0,0,0,0,0,0}
//{10,20,30,40,50,0,0,0,0,0}
//将原数组数据复制到新数组中
System.arraycopy(a,0,newA,0,a.length);
//将原数组的地址转换为新数组地址
a = newA;
Arrays.copyOf
- 新数组地址 java.util.Arrays.copyOf(原数组名,预期的数组长度)
int[] a = {10, 20, 30, 40, 50};
//对a进行扩容并将返回的新数组地址赋值给原数组
a=Arrays.copyOf(a, a.length * 2);
排序
冒泡排序
- 思路:让相邻两个位置的值进行比较,根据比较结果决定是否换位
- 特点:每轮比较之后,都会从后往前确定一个位置的值
- 实现:外层循环代表比较轮数,内层循环代表比较次数
int[] a = {3, 17, 88, 66, 99};
/* 从大到小
第1轮:
第1次(0-1):17 3 88 66 99
第2次(1-2):17 88 3 66 99
第3次(2-3):17 88 66 3 99
第4次(3-4):17 88 66 99 3
第2轮:
第1次(0-1):88 17 66 99 3
第2次(1-2):88 66 17 99 3
第3次(2-3):88 66 99 17 3
第3轮:
第1次(0-1):88 66 99 17 3
第2次(1-2):88 99 66 17 3
第4轮:
第1次(0-1):99 88 66 17 3
* */
for (int i = 1; i < a.length; i++) {//轮数
for (int j = 0; j < a.length-i; j++) {//次数 j=下标
//让当前的a[j]与a[j+1]进行值的比较
//从大到小
if (a[j + 1] < a[j]) {//从小到大:替换为<即可
int temp = a[j + 1];
a[j + 1] = a[j];
a[j] = temp;
}
}
}
选择排序
- 思路:固定一个下标位置,让其他位置与该位置的值进行比较,根据比较结果决定是否换位
- 特点:每轮比较结束之后,固定下标位置的值能被确定
- 实现:外层循环表示固定下标,内层循环表示与其比较的下标
int[] a = {3, 17, 88, 66, 99};
/* 从大到小
固定下标0:
下标1: 17 3 88 66 99
下标2: 88 3 17 66 99
下标3: 88 3 17 66 99
下标4: 99 3 17 66 88
固定下标1:
下标2: 99 17 3 66 88
下标3: 99 66 3 17 88
下标4: 99 88 3 17 66
固定下标2:
下标3:99 88 17 3 66
下标4:99 88 66 3 17
固定下标3:
下标4: 99 88 66 17 3
* */
for (int i = 0; i < a.length - 1; i++) {//固定下标的范围
for (int j = i + 1; j < a.length; j++) {//与其比较的下标
if (a[j] > a[i]) {//从大到小:> 从小到大:<
int temp = a[j];
a[j] = a[i];
a[i] = temp;
}
}
}
JDK排序
- java.util.Arrays.sort(数组名)
int[] a = {3, 17, 88, 66, 99};
Arrays.sort(a);
今日掌握
- 数组的创建语法
- 下标的使用
- 数组的数据类型
- 引用类型之间相互赋值的特点
- 数组扩容的步骤
- 冒泡排序与选择排序的思路特点+JDK排序的写法