08 - 数组:多维数组、Arrays 工具类、排序
08 - 数组:多维数组、Arrays 工具类、排序
一维数组
public class ArrayBasics {
public static void main(String[] args) {
// 声明与创建
int[] arr1 = new int[5]; // 动态初始化,默认值 0
int[] arr2 = {1, 2, 3, 4, 5}; // 静态初始化
int[] arr3 = new int[]{10, 20, 30}; // 匿名数组
// 访问与修改
arr1[0] = 100;
arr1[4] = 500;
System.out.println(arr2[0]); // 1
System.out.println(arr2.length); // 5
// 遍历
for (int i = 0; i < arr2.length; i++) {
System.out.print(arr2[i] + " ");
}
System.out.println();
// 增强 for
for (int n : arr2) {
System.out.print(n + " ");
}
System.out.println();
// ⚠️ 数组越界
// arr2[5] = 99; // ArrayIndexOutOfBoundsException
// 默认值
int[] ints = new int[3]; // [0, 0, 0]
double[] doubles = new double[3]; // [0.0, 0.0, 0.0]
boolean[] bools = new boolean[3]; // [false, false, false]
String[] strings = new String[3]; // [null, null, null]
System.out.println(java.util.Arrays.toString(ints));
}
}
多维数组
public class MultiArrayDemo {
public static void main(String[] args) {
// 二维数组:矩阵
int[][] matrix = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
// 访问
System.out.println(matrix[1][2]); // 6(第2行第3列)
// 遍历二维数组
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
System.out.printf("%4d", matrix[i][j]);
}
System.out.println();
}
// 增强 for 遍历
for (int[] row : matrix) {
for (int val : row) {
System.out.printf("%4d", val);
}
System.out.println();
}
// 不规则数组(锯齿数组)
int[][] jagged = new int[3][];
jagged[0] = new int[]{1};
jagged[1] = new int[]{2, 3};
jagged[2] = new int[]{4, 5, 6};
// 三维数组
int[][][] cube = new int[2][3][4];
cube[0][1][2] = 42;
System.out.println("三维: " + cube[0][1][2]);
// 矩阵转置
int rows = 3, cols = 3;
int[][] transposed = new int[cols][rows];
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
transposed[j][i] = matrix[i][j];
}
}
System.out.println("转置:");
for (int[] row : transposed) {
System.out.println(java.util.Arrays.toString(row));
}
}
}
Arrays 工具类
import java.util.Arrays;
public class ArraysUtilDemo {
public static void main(String[] args) {
int[] arr = {5, 2, 8, 1, 9, 3, 7, 4, 6};
// toString —— 数组转字符串
System.out.println(Arrays.toString(arr));
// sort —— 排序
Arrays.sort(arr);
System.out.println("排序后: " + Arrays.toString(arr));
// binarySearch —— 二分查找(必须已排序)
int idx = Arrays.binarySearch(arr, 7);
System.out.println("7 的索引: " + idx);
// copyOf / copyOfRange —— 复制
int[] copy = Arrays.copyOf(arr, 5);
int[] range = Arrays.copyOfRange(arr, 2, 6);
System.out.println("复制前5: " + Arrays.toString(copy));
System.out.println("范围[2,6): " + Arrays.toString(range));
// fill —— 填充
int[] filled = new int[5];
Arrays.fill(filled, 42);
System.out.println("填充: " + Arrays.toString(filled));
// equals —— 比较
int[] a = {1, 2, 3};
int[] b = {1, 2, 3};
System.out.println("equals: " + Arrays.equals(a, b)); // true
// deepEquals —— 深比较(多维数组)
int[][] m1 = {{1, 2}, {3, 4}};
int[][] m2 = {{1, 2}, {3, 4}};
System.out.println("deepEquals: " + Arrays.deepEquals(m1, m2)); // true
// hashCode / deepHashCode
System.out.println("hashCode: " + Arrays.hashCode(a));
System.out.println("deepHashCode: " + Arrays.deepHashCode(m1));
// asList —— 数组转 List
String[] names = {"张三", "李四", "王五"};
java.util.List<String> nameList = Arrays.asList(names);
System.out.println("List: " + nameList);
// stream(JDK 8+)
int sum = Arrays.stream(arr).sum();
int max = Arrays.stream(arr).max().orElse(0);
System.out.println("总和: " + sum + ", 最大值: " + max);
}
}
排序算法
内置排序
import java.util.Arrays;
import java.util.Comparator;
public class SortDemo {
public static void main(String[] args) {
// 基本类型排序(双轴快排 TimSort)
int[] nums = {5, 2, 8, 1, 9, 3};
Arrays.sort(nums);
System.out.println(Arrays.toString(nums)); // [1, 2, 3, 5, 8, 9]
// 部分排序(parallelSort 更适合大数组)
int[] big = new int[10000];
Arrays.fill(big, 0);
Arrays.parallelSort(big);
// 对象数组排序
String[] names = {"Charlie", "Alice", "Bob"};
Arrays.sort(names); // 自然顺序
System.out.println(Arrays.toString(names)); // [Alice, Bob, Charlie]
// 自定义排序
Arrays.sort(names, Comparator.reverseOrder());
System.out.println(Arrays.toString(names)); // [Charlie, Bob, Alice]
// 按长度排序
Arrays.sort(names, Comparator.comparingInt(String::length));
System.out.println(Arrays.toString(names));
// 二维数组排序
int[][] points = {{3, 1}, {1, 5}, {2, 3}};
Arrays.sort(points, Comparator.comparingInt((int[] p) -> p[0])
.thenComparingInt(p -> p[1]));
for (int[] p : points) {
System.out.println(Arrays.toString(p));
}
}
}
手动实现排序
public class SortAlgorithms {
// 冒泡排序 — O(n²)
static void bubbleSort(int[] arr) {
int n = arr.length;
for (int i = 0; i < n - 1; i++) {
boolean swapped = false;
for (int j = 0; j < n - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
swapped = true;
}
}
if (!swapped) break; // 已有序,提前退出
}
}
// 快速排序 — O(n log n)
static void quickSort(int[] arr, int lo, int hi) {
if (lo >= hi) return;
int pivot = arr[hi];
int i = lo;
for (int j = lo; j < hi; j++) {
if (arr[j] < pivot) {
int tmp = arr[i];
arr[i++] = arr[j];
arr[j] = tmp;
}
}
arr[hi] = arr[i];
arr[i] = pivot;
quickSort(arr, lo, i - 1);
quickSort(arr, i + 1, hi);
}
public static void main(String[] args) {
int[] a = {5, 2, 8, 1, 9, 3};
bubbleSort(a);
System.out.println("冒泡排序: " + java.util.Arrays.toString(a));
int[] b = {5, 2, 8, 1, 9, 3};
quickSort(b, 0, b.length - 1);
System.out.println("快速排序: " + java.util.Arrays.toString(b));
}
}
常见排序算法对比
| 算法 | 平均时间 | 最坏时间 | 空间 | 稳定性 |
|---|---|---|---|---|
| 冒泡排序 | O(n²) | O(n²) | O(1) | ✅ 稳定 |
| 选择排序 | O(n²) | O(n²) | O(1) | ❌ 不稳定 |
| 插入排序 | O(n²) | O(n²) | O(1) | ✅ 稳定 |
| 希尔排序 | O(n^1.3) | O(n²) | O(1) | ❌ 不稳定 |
| 归并排序 | O(n log n) | O(n log n) | O(n) | ✅ 稳定 |
| 快速排序 | O(n log n) | O(n²) | O(log n) | ❌ 不稳定 |
| 堆排序 | O(n log n) | O(n log n) | O(1) | ❌ 不稳定 |
| TimSort | O(n log n) | O(n log n) | O(n) | ✅ 稳定 |
💡 Java 内置
Arrays.sort()使用 TimSort(混合排序),综合了归并排序和插入排序的优势。
⚠️ 注意事项
- 数组长度不可变 — 创建后不能增减长度,需要变长使用
ArrayList。 - 数组越界 — 访问
arr[arr.length]会抛ArrayIndexOutOfBoundsException。 Arrays.asList()返回的列表不可增删 — 底层仍指向原数组,add()/remove()会抛异常。- 多维数组比较用
deepEquals—equals只比较引用。 binarySearch必须已排序 — 未排序结果不可预测。
💡 技巧
数组转 List 的正确方式:
// ❌ 不可变 List<String> list = Arrays.asList("A", "B"); // ✅ 可变 List<String> mutable = new ArrayList<>(Arrays.asList("A", "B")); // ✅ JDK 9+ 最简洁 List<String> fixed = List.of("A", "B"); // 不可变数组去重:
int[] arr = {1, 2, 2, 3, 3, 3}; int[] unique = Arrays.stream(arr).distinct().toArray();数组反转:
// 使用 Collections(对象数组) List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C")); Collections.reverse(list); // 手动反转(基本类型数组) int[] arr = {1, 2, 3, 4, 5}; for (int i = 0, j = arr.length - 1; i < j; i++, j--) { int tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp; }
🏢 业务场景
- 数据处理: 矩阵运算、图像处理、科学计算。
- 算法题: LeetCode、面试算法题的基础数据结构。
- 性能敏感场景: 数组访问 O(1),比 ArrayList 更高效(无装箱开销)。
- 字节缓冲区: 网络编程中使用
byte[]作为数据缓冲区。