第 12 章:数组
学习目标
- 掌握一维、二维数组的声明和使用
- 学会 Arrays 工具类的常用方法
- 理解数组与 List 的互转
- 避免数组的常见坑
一、什么是数组?
数组 = 相同类型数据的有序集合,长度固定。
java
int[] scores = {85, 92, 78, 95, 88};
// ↓ ↓ ↓
// 类型 引用 5 个 int 元素二、一维数组
2.1 声明方式(两种)
java
// ✅ 推荐:类型在前
int[] arr1;
// ⚠️ C 风格:可读性差
int arr2[];2.2 创建数组
java
// 方式 1:声明时初始化(最常用)
int[] scores = {85, 92, 78, 95, 88};
// 方式 2:new + 初始化器(适合动态数据)
int[] ages = new int[]{18, 25, 30};
// 方式 3:new + 指定长度(默认 0)
int[] arr = new int[5]; // 5 个 0
String[] names = new String[3]; // 3 个 null
// 方式 4:先声明再创建
int[] nums;
nums = new int[10];2.3 访问元素
java
int[] arr = {10, 20, 30, 40, 50};
System.out.println(arr[0]); // 10(第一个元素)
System.out.println(arr[4]); // 50(最后一个元素)
arr[0] = 100; // 修改第一个元素
// arr[5] = 60; // ❌ ArrayIndexOutOfBoundsException2.4 数组长度
java
int[] arr = {10, 20, 30};
System.out.println(arr.length); // 3(数组 length 是属性,不是方法)三、二维数组
二维数组是"数组的数组"。
java
// 声明
int[][] matrix;
// 创建 3×4 矩阵
matrix = new int[3][4];
// 声明并初始化
int[][] matrix2 = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
// 访问
System.out.println(matrix2[0][0]); // 1
System.out.println(matrix2[1][2]); // 7
matrix2[2][3] = 100;3.1 不规则二维数组
java
// 每行长度可以不同
int[][] jagged = {
{1, 2},
{3, 4, 5, 6},
{7}
};
System.out.println(jagged[0].length); // 2
System.out.println(jagged[1].length); // 4
System.out.println(jagged[2].length); // 1四、数组的内存模型
关键点:
- 数组是引用类型,引用在栈
- 实际数据在堆
- 一旦创建,长度不可变
五、数组遍历
5.1 for 循环(经典)
java
int[] arr = {85, 92, 78, 95, 88};
for (int i = 0; i < arr.length; i++) {
System.out.println("arr[" + i + "] = " + arr[i]);
}5.2 for-each(推荐)
java
for (int score : arr) {
System.out.println(score);
}5.3 二维数组遍历
java
int[][] matrix = {{1, 2, 3}, {4, 5, 6}};
for (int[] row : matrix) { // ① 外层遍历行
for (int num : row) { // ② 内层遍历每行元素
System.out.print(num + " ");
}
System.out.println();
}六、Arrays 工具类
java.util.Arrays 提供大量数组操作方法。
6.1 打印数组
java
int[] arr = {3, 1, 4, 1, 5, 9, 2, 6};
System.out.println(Arrays.toString(arr));
// [3, 1, 4, 1, 5, 9, 2, 6]
int[][] matrix = {{1, 2}, {3, 4}};
System.out.println(Arrays.deepToString(matrix));
// [[1, 2], [3, 4]]6.2 排序
java
int[] arr = {3, 1, 4, 1, 5, 9, 2, 6};
Arrays.sort(arr); // 升序排序(双轴快排 + TimSort)
System.out.println(Arrays.toString(arr));
// [1, 1, 2, 3, 4, 5, 6, 9]6.3 填充
java
int[] arr = new int[5];
Arrays.fill(arr, 100);
System.out.println(Arrays.toString(arr));
// [100, 100, 100, 100, 100]6.4 二分查找(必须先排序)
java
int[] arr = {1, 3, 5, 7, 9, 11};
int index = Arrays.binarySearch(arr, 7); // 3
int notFound = Arrays.binarySearch(arr, 4); // -3(负数表示未找到)6.5 比较
java
int[] a = {1, 2, 3};
int[] b = {1, 2, 3};
System.out.println(Arrays.equals(a, b)); // true(值相等)
System.out.println(a.equals(b)); // false(继承 Object 的 == 比较)6.6 复制
java
int[] arr = {1, 2, 3, 4, 5};
int[] copy1 = Arrays.copyOf(arr, 5); // 复制前 5 个
int[] copy2 = Arrays.copyOfRange(arr, 1, 4); // 复制 [1, 4)
int[] copy3 = arr.clone(); // 浅拷贝七、数组与 List 互转
7.1 数组 → List
java
String[] arr = {"a", "b", "c"};
// ✅ JDK 9+ 推荐
List<String> list1 = Arrays.asList(arr); // 固定大小 List
List<String> list2 = List.of(arr); // 不可变 List
// ✅ 可变 List
List<String> list3 = new ArrayList<>(Arrays.asList(arr));⚠️
Arrays.asList()返回的 List 长度固定,不能 add/remove。
7.2 List → 数组
java
List<String> list = List.of("a", "b", "c");
String[] arr1 = list.toArray(new String[0]); // ✅ 推荐
String[] arr2 = list.toArray(new String[list.size()]);八、数组的常见坑
8.1 数组越界
java
int[] arr = {1, 2, 3};
// arr[3] = 4; // ❌ ArrayIndexOutOfBoundsException(下标越界)8.2 空指针
java
int[] arr = null;
System.out.println(arr.length); // ❌ NullPointerException8.3 长度不可变
java
int[] arr = {1, 2, 3};
// arr.length = 5; // ❌ 编译报错:length 是 final8.4 默认值陷阱
java
// 基本类型数组:默认 0 / false
int[] nums = new int[3];
System.out.println(nums[0]); // 0(不是 null)
// 引用类型数组:默认 null
String[] strs = new String[3];
System.out.println(strs[0]); // null九、完整代码示例
java
import java.util.Arrays;
import java.util.List;
import java.util.ArrayList;
/**
* 数组综合示例
*
* 配套文档:第 12 章 数组
* 运行方式:javac ArrayDemo.java && java ArrayDemo
*/
public class ArrayDemo {
public static void main(String[] args) {
// ============ 1. 一维数组 ============
System.out.println("=== 一维数组 ===");
int[] scores = {85, 92, 78, 95, 88};
System.out.println("长度: " + scores.length);
System.out.println("第一个: " + scores[0]);
System.out.println("最后一个: " + scores[scores.length - 1]);
// 修改元素
scores[0] = 100;
System.out.println("修改后: " + Arrays.toString(scores));
// ============ 2. 遍历 ============
System.out.println("\n=== 遍历 ===");
for (int i = 0; i < scores.length; i++) {
System.out.println("for [" + i + "] = " + scores[i]);
}
System.out.println("---");
for (int score : scores) {
System.out.println("for-each = " + score);
}
// ============ 3. 二维数组 ============
System.out.println("\n=== 二维数组 ===");
int[][] matrix = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
System.out.println("行数: " + matrix.length);
System.out.println("第一行列数: " + matrix[0].length);
System.out.println("matrix[1][2] = " + matrix[1][2]); // 7
// 遍历二维数组
for (int[] row : matrix) {
for (int num : row) {
System.out.printf("%4d", num);
}
System.out.println();
}
// ============ 4. Arrays 工具类 ============
System.out.println("\n=== Arrays 工具类 ===");
int[] arr = {3, 1, 4, 1, 5, 9, 2, 6};
System.out.println("原数组: " + Arrays.toString(arr));
Arrays.sort(arr);
System.out.println("排序后: " + Arrays.toString(arr));
Arrays.fill(arr, 0);
System.out.println("填充后: " + Arrays.toString(arr));
// ============ 5. 数组与 List 互转 ============
System.out.println("\n=== 数组与 List 互转 ===");
String[] strArr = {"a", "b", "c"};
// 数组 → List
List<String> list1 = new ArrayList<>(Arrays.asList(strArr));
list1.add("d"); // ✅ 可变 List
System.out.println("List: " + list1);
// List → 数组
String[] newArr = list1.toArray(new String[0]);
System.out.println("Array: " + Arrays.toString(newArr));
// ============ 6. 实战:找数组中的最大值 ============
System.out.println("\n=== 实战:数组操作 ===");
int[] data = {23, 45, 12, 67, 34, 89, 5};
int max = data[0];
int min = data[0];
int sum = 0;
for (int n : data) {
if (n > max) max = n;
if (n < min) min = n;
sum += n;
}
double avg = (double) sum / data.length;
System.out.println("最大值: " + max);
System.out.println("最小值: " + min);
System.out.println("总和: " + sum);
System.out.println("平均值: " + avg);
}
}运行结果:
=== 一维数组 ===
长度: 5
第一个: 85
最后一个: 88
修改后: [100, 92, 78, 95, 88]
...十、动手练习
练习 1:基础题
写一个 ArrayUtils 类,实现:
java
public static int max(int[] arr) // 最大值
public static int min(int[] arr) // 最小值
public static double average(int[] arr) // 平均值
public static int[] reverse(int[] arr) // 反转练习 2:进阶题
实现数组去重(保留第一次出现的元素顺序):
java
int[] input = {1, 2, 3, 2, 1, 4, 5, 4};
int[] output = unique(input);
// 输出: [1, 2, 3, 4, 5]练习 3:挑战题
实现一个学生成绩统计小项目:
=== 成绩统计 ===
请输入学生人数:5
请输入 5 个成绩(0-100):
张三 85
李四 92
王五 78
赵六 95
钱七 88
=== 统计结果 ===
平均分:87.6
最高分:95(赵六)
最低分:78(王五)
及格人数:4
优秀人数(>=90):2十一、本章小结
| 要点 | 关键 |
|---|---|
| 数组本质 | 固定长度的同类数据集合 |
| 声明方式 | int[] arr(推荐)或 int arr[] |
| 内存模型 | 引用在栈,数据在堆 |
| 遍历方式 | for / for-each |
| 工具类 | Arrays.sort、Arrays.toString、Arrays.binarySearch 等 |
| 数组转 List | Arrays.asList()(长度固定)或 new ArrayList<>() |
| 常见坑 | 越界、空指针、长度不可变 |
推荐阅读
- 📖 《Java 核心技术》卷 1 第 3.10 节 — 数组详解
- 📖 《算法》第四版 第 1 章 — 数组与算法
下一章:第 13 章:面向对象思想 →