目录
1. 数组的基本概念
1.1 什么是数组
【定义】数组是相同类型元素的集合,在内存上连续,每个空间有自己的编号(从0开始)
1.2 数组的创建及初始化
1. 创建数组
//数组的创建
int n = 2;
int[] a = new int[n]; //用变量创建
int[] b = new int[2]; //用常量创建
2. 初始化数组
数组初始化分为静态初始化和动态初始化。
【静态初始化】创建数组时,直接对数组元素赋值,而不直接指定数组元素个数(编译器会自动计算数组的个数)
【动态初始化】创建数组时,直接指定数组元素个数
//方式一: 静态初始化
//正式格式
int[] arr = {1,2,3};
//省略格式
int[] arr1 = new int[]{1,2};
//方式二: 动态初始化
int[] arr2 = new int[5];
//方式三: 分两步初始化数组
int[] c; //步骤一
c = new int[2]; //步骤二
c = new int[]{1,5}; //步骤二
c = {1,5,8}; //错误写法
【注】
- 数组初始化可以写成两步,但正式格式不能写在第二步,只能写省略格式和动态初始化
- 若只创建数组,没有对数组初始化,则编译器会根据其数组内的元素类型来给默认值
【基本数据类型的默认值】
整数默认值为0;
浮点数float默认值为0.0f,double默认值0.0;
字符默认值/u0000;
布尔默认值false
3. 遍历数组
数组中,通过"数组名.length"来计算数组长度,可以用for或for-each循环,但for-each循环不能按下标查找元素
【for种类】
for循环
for-each循环
2. 深入理解数组
2.1 数组的数据类型
数组是引用数据类型,该类型定义的变量叫引用变量(引用);基本数据类型定义的变量叫基本变量。
方法中的变量都存在该方法的栈帧中,而栈帧存在虚拟机栈中。
2.2 JVM内存分布
内存用于存储程序运行时的数据,比如,
- 代码要加载到内存
- 运行时产生的中间数据要保存
- 常量也需要保存
- 有些数据需要长时间保存,也有些数据需要用完销毁 这些混乱的数据就如同房间的各种物品一样,需要归纳整理,因此JVM也对内存进行了划分。
【JVM内存分布图示】
- 虚拟机栈:存放栈帧。每个方法在调用前会创建栈帧,栈帧中存放方法中的变量,比如main方法调用时也会创建栈帧
- 堆:存放new创建的对象
- 程序计数器:只有很小的内存,存放下一条执行的指令的地址
- 方法区:存放类的信息,常量,静态变量等数据。
- 其他的省略,后续详细讲
【代码示例】
public static void main(String[] args) {
int[] arr = {1, 2, 3};
func(arr);
}
public static void func() {
int a = 10;
int b = 20;
int[] arr = new int[]{1,2,3};
}
【代码运行图示】
【代码文字说明】
func方法在虚拟机栈中创建栈帧,基本变量a,b和引用变量arr都在func方法栈帧中。a,b存的是它们初始化的值,arr存的是数组在堆中的首地址,通过该地址可访问到堆中的数组元素
2.3 null
当引用变量赋值为null时,代表该变量指向一个无效内存位置,但null 和 0 号地址的内存没有任何关联
2.4 数组的使用方式
1. 保存数据
int[] arr = {1, 2, 3};
2. 作方法参数
public static void main(String[] args) {
int[] arr = {1, 2, 3};
func(arr);
System.out.println("arr[0] = " + arr[0]);
}
public static void func(int[] a) {
a[0] = 10;
System.out.println("a[0] = " + a[0]);
}
// 执行结果 a[0] = 10 arr[0] = 10
- 用基本变量传参,形参是实参的一份临时拷贝,修改形参不影响实参
- 用引用变量传参,形参不再是拷贝,而是通过传来的地址指向了实参所指向的堆中地址,修改形参影响实参
3. 作方法的返回值
public static int[] reverse(int[] arr){
int i = 0;
int j = arr.length-1;
while(i <= j) { //数组个数为奇数个或偶数个
//交换
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
i++;
j--;
}
return arr;
}
public static void main(String[] args) {
int[] arr = new int[]{1,2,3,4,5};
System.out.println(Arrays.toString(reverse(arr)));
}
3. 数组相关操作
3.1 数组转字符串
Arrays.toString(数组),返回值是String类型
3.2 数组拷贝
Arrays.copyOf(拷贝哪个数组,想拷贝的长度),返回值是数组类型
3.3 二分查找
public static int binary(int key,int[] arr){
int i = 0;
int j = arr.length-1;
while(i<=j){
int mid = (i+j)/2;
if (key < arr[mid]){
j = mid-1;
}else if(key == arr[mid]){
return mid;
}else {
i = mid +1;
}
}
return -1;
}
public static void main(String[] args) {
//二分查找指定元素的下标
int[] arr = new int[]{1,2,3,5,8};
System.out.println(binary(5,arr));
}
3.4 冒泡排序
public static void bubble(int[] arr){
int tmp = 0;
int flg = 0;
for (int i = 0;i<arr.length-1;i++){
for (int j = 0;j<arr.length-1-i;j++){
flg = -1;
if(arr[j] > arr[j+1]){
//交换
tmp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = tmp;
flg *= -1;
}
}
//交换完flg一定为1,没交换一定是-1
if (flg == -1){
return;
}
}
}
public static void main(String[] args) {
//冒泡排序
int[] arr = new int[]{55,68,24,1,7};
bubble(arr);
System.out.println(Arrays.toString(arr));
}
3.5 数组逆序
public static int[] reverse(int[] arr){
int i = 0;
int j = arr.length-1;
while(i <= j) { //数组个数为奇数个或偶数个
//交换
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
i++;
j--;
}
return arr;
}
public static void main(String[] args) {
int[] arr = new int[]{1,2,3,4,5};
System.out.println(Arrays.toString(reverse(arr)));
}
4. 二维数组
二维数组是特殊的一维数组
【代码演示】
public static void main(String[] args) {
//创建方式一
int[][] arr = new int[][]{{1,2,3},{4,5,6},{7,8,9}};
System.out.println(Arrays.toString(arr)); //[[I@311d617d, [I@7c53a9eb, [I@ed17bee]
System.out.println(Arrays.deepToString(arr)); //[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
//创建方式二
int[][] array = {{11,21,31},{4,5,6},{7,8,9}};
System.out.println(Arrays.deepToString(array)); //[[11, 21, 31], [4, 5, 6], [7, 8, 9]]
//创建方式三
int[][] array1 = new int[2][];
System.out.println(Arrays.deepToString(array1)); //[null, null]
}
【二维数组图示】