强曰为道

与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

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)❌ 不稳定
TimSortO(n log n)O(n log n)O(n)✅ 稳定

💡 Java 内置 Arrays.sort() 使用 TimSort(混合排序),综合了归并排序和插入排序的优势。

⚠️ 注意事项

  1. 数组长度不可变 — 创建后不能增减长度,需要变长使用 ArrayList
  2. 数组越界 — 访问 arr[arr.length] 会抛 ArrayIndexOutOfBoundsException
  3. Arrays.asList() 返回的列表不可增删 — 底层仍指向原数组,add()/remove() 会抛异常。
  4. 多维数组比较用 deepEqualsequals 只比较引用。
  5. binarySearch 必须已排序 — 未排序结果不可预测。

💡 技巧

  1. 数组转 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");       // 不可变
    
  2. 数组去重

    int[] arr = {1, 2, 2, 3, 3, 3};
    int[] unique = Arrays.stream(arr).distinct().toArray();
    
  3. 数组反转

    // 使用 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[] 作为数据缓冲区。

📖 扩展阅读