1 数组的定义
- 数组是相同类型数据的有序集合
- 数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成
- 每一个数据称为一个数组元素,每个数组元素可以通过一个下标访问
2 数组声明创建
-
必须声明数组变量,才能在程序中使用数组
dataType[] arrayRefVar; // 首选方法 dataType arrayRefVar[]; // 效果相同,但不推荐
-
Java使用
new
操作符创建数组dataType arrayRefVar = new dataType[arraySize];
-
数组的元素通过索引(下标)访问,数组索引从0开始
-
通过
arrays.length
获取数组长度
3 简单内存分析
4 数组初始化
-
静态初始化
// 创建 + 赋值 int[] a = {1, 2, 3}; Man[] mans = {new Man(1, 1), new Man(2, 2)};
-
动态初始化
// 包含默认初始化 int[] a = new int[2]; a[0] = 1; a[1] = 2;
-
默认初始化:数组是引用类型,它的元素相当于类的实例变量,因此数组一经分配空间,其中的每个元素也被按照实例变量同样的方式被隐式初始化
5 数组基本特点
- 数组长度确定,数组一旦被创建,其大小不可改变
- 数组中元素必须是相同类型,不允许出现混合类型
- 数组中的元素可以是任何数据类型,包括基本类型和引用类型
- 数组变量属于引用变量,也可以看做对象,数组中的每个元素相当于该对象的成员变量
- Java中对象在堆中,所以数组对象本身也在堆中
6 数组边界
索引(下标)的合法区间:[0, length - 1],如果越界会报ArrayIndexOutOfBoundsException
,数组索引越界异常
7 数组使用
-
增强for循环
int[] array = {1, 2, 3, 4, 5}; // 普通for循环通过索引遍历数组 for (int i = 0; i < array.length; i++) { System.out.println(array[i]); } // 增强for-each循环遍历数组 for (int num : array) { System.out.println(num); }
-
数组作为参数和返回值
// 反转数组 public static int[] reverse(int[] array) { int len = array.length; int[] result = new int[len]; for (int i = 0,; i < len - 1; i++) { result[len - 1 - i] = array[i]; } return result; }
8 多维数组
多维数组可以看做是数组的数组,例如二维数组就是一个特殊的一维数组,其每个元素都是一个一维数组
int arr[][] = new int[2][3]; // 可看成一个两行三列的数组
int arr[][] = {{1, 2, 3}, {4, 5, 6}}; // 静态初始化
内部结构如下所示
9 Arrays
类
-
Arrays
类是数组的工具类,位于java.util.Arrays
-
数组对象本身并没有什么方法可以供我们调用,工具类
Arrays
可以对数组对象进行一些基本的操作 -
Arrays
类中的方法都是由static
修饰的静态方法,使用时可以直接以类名调用 -
Arrays
类有以下常用功能-
赋值:
fill()
方法Arrays.fill(arr, 1); // 全部赋值为1 Arrays.fill(arr, 2, 4, 1); // arr[2]和arr[3]赋值为1,索引左闭右开
-
排序:
sort()
方法,升序 -
比较数组:通过
equals()
方法比较数组中元素值是否相等 -
查找数组元素:通过
binarySearch()
方法对排序好的数组进行二分查找 -
打印数组:
toString()
-
10 冒泡排序
冒泡排序是最出名的排序算法之一,有两层循环,外层为冒泡轮数,内层依次比较,时间复杂度为O(n^2)
// 升序冒泡排序
public static void bubbleSort(int[] arr) {
for (int i = 0; i < arr.length - 1; i++) {
boolean flag = false; // 标志位
for (int j = 0; j < arr.length - 1 - i; j++) {
if (arr[j] > arr[j + 1]) { // 每次将当前最大数放在末尾
int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
flag = true; // 如果有过交换,改变标志位
}
}
if (!flag) { // 如果标志位没有发生变化,说明没有发生过交换,此时完成排序
break;
}
}
}
11 稀疏数组(扩展)
-
当一个数组中大部分元素为0,或为同一个值时,可以使用稀疏数组来保存该数组
-
稀疏数组的处理方式:
- 第一行存储原始数据总行数,总列数,总的非0数据(不同数据)个数
- 接下来每一行都存储非0数据所在行,所在列和其具体值
-
左边为原始数组,右边为稀疏数组
-
将原始数组转换为稀疏数组
public static int[][] transfer(int[][] arr) { int row = arr.length; int col = arr[0].length; // 获取有效值的个数 int sum = 0; for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { if (arr[i][j] != 0) { sum++; } } } // 创建一个稀疏数组 int[][] result = new int[sum + 1][3]; // 第一行数据 result[0][0] = row; result[0][1] = col; result[0][2] = sum; // 遍历二维数组,将非零值存放在稀疏数组中 int count = 0; for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { if (arr[i][j] != 0) { count++; result[count][0] = i; result[count][1] = j; result[count][2] = arr[i][j]; } } } return result; }
-
由稀疏数组还原原始数组
public static int[][] recovery(int[][] arr) { // 读取稀疏数组 int[][] result = new int[arr[0][0]][arr[0][1]]; // 还原值 for (int i = 1; i < arr.length; i++) { result[arr[i][0]][arr[i][1]] = arr[i][2]; } return result; }