跳转至

数组

数组是 Java 中用于存储固定大小同类型元素的数据结构。数组在内存中是连续存储的,可以通过索引快速访问任意位置的元素。本章将详细介绍数组的基本概念、创建方式、常用操作以及实际应用场景。

1. 数组的基本概念

什么是数组?

数组是一种线性数据结构,用于存储相同类型的多个元素。在 Java 中,数组具有以下特点:

  • 固定大小:数组一旦创建,其大小就不能改变
  • 相同类型:数组中的所有元素必须是相同的数据类型
  • 连续内存:数组元素在内存中是连续存储的
  • 索引访问:通过从0开始的整数索引访问元素

数组的内存表示

1
2
3
索引:   0     1     2     3     4
值:   [10]  [20]  [30]  [40]  [50]
地址: 1000  1004  1008  1012  1016  (假设int占4字节)

2. 数组的声明与初始化

2.1 数组的声明语法

Java 提供了两种声明数组的语法:

1
2
3
4
5
// 方式1:类型后跟方括号(推荐)
int[] numbers;

// 方式2:变量名后跟方括号(C语言风格)
int numbers[];

推荐使用第一种方式,因为它更清晰地表明 numbers 是一个 int 类型的数组。

2.2 数组的初始化方法

数组可以通过多种方式初始化:

方法一:声明时直接初始化

public class ArrayExample {
    public static void main(String[] args) {
        // 声明并初始化数组(使用花括号)
        int[] numbers = {1, 2, 3, 4, 5};

        // 声明字符串数组
        String[] fruits = {"Apple", "Banana", "Orange"};

        // 声明布尔数组
        boolean[] flags = {true, false, true};
    }
}

方法二:先声明后初始化

public class ArrayExample {
    public static void main(String[] args) {
        // 声明数组(指定大小)
        int[] numbers = new int[5];  // 创建包含5个int元素的数组,默认值为0

        // 逐个赋值
        numbers[0] = 10;
        numbers[1] = 20;
        numbers[2] = 30;
        numbers[3] = 40;
        numbers[4] = 50;

        // 声明字符串数组
        String[] names = new String[3];  // 创建包含3个String元素的数组,默认值为null
        names[0] = "Alice";
        names[1] = "Bob";
        names[2] = "Charlie";
    }
}

方法三:使用循环初始化

public class ArrayExample {
    public static void main(String[] args) {
        // 创建包含10个元素的数组
        int[] squares = new int[10];

        // 使用循环初始化数组
        for (int i = 0; i < squares.length; i++) {
            squares[i] = (i + 1) * (i + 1);  // 存储1-10的平方
        }

        // 打印数组内容
        for (int i = 0; i < squares.length; i++) {
            System.out.println((i + 1) + "的平方是: " + squares[i]);
        }
    }
}

2.3 数组的默认值

当创建数组但不显式初始化时,Java 会根据元素类型赋予默认值:

数据类型 默认值
byteshortintlong 0
floatdouble 0.0
char '\u0000'(空字符)
boolean false
引用类型(如 String null
public class DefaultValues {
    public static void main(String[] args) {
        int[] intArray = new int[3];
        double[] doubleArray = new double[3];
        boolean[] boolArray = new boolean[3];
        String[] strArray = new String[3];

        System.out.println("int数组默认值: " + Arrays.toString(intArray));
        System.out.println("double数组默认值: " + Arrays.toString(doubleArray));
        System.out.println("boolean数组默认值: " + Arrays.toString(boolArray));
        System.out.println("String数组默认值: " + Arrays.toString(strArray));
    }
}

3. 数组的访问与遍历

3.1 访问数组元素

通过索引访问数组元素,索引范围从 0 到 数组长度-1

public class ArrayAccess {
    public static void main(String[] args) {
        int[] scores = {85, 92, 78, 95, 88};

        // 访问第一个元素
        int firstScore = scores[0];  // 85

        // 访问最后一个元素
        int lastScore = scores[scores.length - 1];  // 88

        // 修改数组元素
        scores[2] = 85;  // 将第三个元素从78改为85

        System.out.println("修改后的第三个分数: " + scores[2]);
    }
}

3.2 遍历数组的方法

Java 提供了多种遍历数组的方式:

方法一:使用 for 循环

public class ArrayTraversal {
    public static void main(String[] args) {
        int[] numbers = {10, 20, 30, 40, 50};

        // 传统for循环
        System.out.println("使用传统for循环:");
        for (int i = 0; i < numbers.length; i++) {
            System.out.println("索引 " + i + ": " + numbers[i]);
        }
    }
}

方法二:使用增强 for 循环(for-each)

public class ArrayTraversal {
    public static void main(String[] args) {
        int[] numbers = {10, 20, 30, 40, 50};

        // 增强for循环(for-each)
        System.out.println("使用增强for循环:");
        for (int num : numbers) {
            System.out.println(num);
        }
    }
}

方法三:使用 while 循环

public class ArrayTraversal {
    public static void main(String[] args) {
        int[] numbers = {10, 20, 30, 40, 50};

        // while循环
        System.out.println("使用while循环:");
        int i = 0;
        while (i < numbers.length) {
            System.out.println(numbers[i]);
            i++;
        }
    }
}

3.3 获取数组长度

使用 length 属性获取数组的长度:

public class ArrayLength {
    public static void main(String[] args) {
        int[] numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

        System.out.println("数组长度: " + numbers.length);  // 10

        // 计算数组元素总和
        int sum = 0;
        for (int i = 0; i < numbers.length; i++) {
            sum += numbers[i];
        }

        System.out.println("数组元素总和: " + sum);
        System.out.println("数组平均值: " + (double)sum / numbers.length);
    }
}

4. 多维数组

Java 支持多维数组,最常见的是二维数组,可以理解为"数组的数组"。

4.1 二维数组的声明与初始化

方法一:直接初始化

public class TwoDArrayExample {
    public static void main(String[] args) {
        // 声明并初始化二维数组
        int[][] matrix = {
            {1, 2, 3},     // 第一行
            {4, 5, 6},     // 第二行
            {7, 8, 9}      // 第三行
        };

        // 访问二维数组元素
        System.out.println("matrix[0][0] = " + matrix[0][0]);  // 1
        System.out.println("matrix[1][2] = " + matrix[1][2]);  // 6
        System.out.println("matrix[2][1] = " + matrix[2][1]);  // 8
    }
}

方法二:先声明后初始化

public class TwoDArrayExample {
    public static void main(String[] args) {
        // 声明3行4列的二维数组
        int[][] matrix = new int[3][4];

        // 使用嵌套循环初始化
        for (int i = 0; i < matrix.length; i++) {          // 遍历行
            for (int j = 0; j < matrix[i].length; j++) {   // 遍历列
                matrix[i][j] = (i + 1) * (j + 1);          // 行号×列号
            }
        }

        // 打印二维数组
        for (int i = 0; i < matrix.length; i++) {
            for (int j = 0; j < matrix[i].length; j++) {
                System.out.print(matrix[i][j] + "\t");
            }
            System.out.println();
        }
    }
}

方法三:不规则数组(每行长度不同)

public class IrregularArray {
    public static void main(String[] args) {
        // 创建不规则二维数组
        int[][] triangle = new int[5][];

        // 为每一行分配不同长度的数组
        for (int i = 0; i < triangle.length; i++) {
            triangle[i] = new int[i + 1];  // 第i行有i+1个元素
        }

        // 初始化并打印
        for (int i = 0; i < triangle.length; i++) {
            for (int j = 0; j < triangle[i].length; j++) {
                triangle[i][j] = (i + 1) * 10 + (j + 1);
                System.out.print(triangle[i][j] + " ");
            }
            System.out.println();
        }
    }
}

4.2 二维数组的遍历

使用嵌套 for 循环

public class TwoDArrayTraversal {
    public static void main(String[] args) {
        int[][] scores = {
            {85, 92, 78},
            {95, 88, 91},
            {76, 84, 90}
        };

        // 遍历所有学生的所有科目成绩
        for (int i = 0; i < scores.length; i++) {
            System.out.print("学生 " + (i + 1) + " 的成绩: ");
            int studentTotal = 0;

            for (int j = 0; j < scores[i].length; j++) {
                System.out.print(scores[i][j] + " ");
                studentTotal += scores[i][j];
            }

            System.out.println("| 总分: " + studentTotal + 
                             ", 平均分: " + (double)studentTotal / scores[i].length);
        }
    }
}

使用增强 for 循环

public class TwoDArrayForEach {
    public static void main(String[] args) {
        int[][] matrix = {
            {1, 2, 3},
            {4, 5, 6},
            {7, 8, 9}
        };

        // 使用增强for循环遍历二维数组
        System.out.println("矩阵内容:");
        for (int[] row : matrix) {
            for (int num : row) {
                System.out.print(num + " ");
            }
            System.out.println();
        }
    }
}

4.3 三维及更高维数组

public class ThreeDArray {
    public static void main(String[] args) {
        // 创建3×3×3的三维数组
        int[][][] cube = new int[3][3][3];

        // 初始化三维数组
        int value = 1;
        for (int i = 0; i < cube.length; i++) {
            for (int j = 0; j < cube[i].length; j++) {
                for (int k = 0; k < cube[i][j].length; k++) {
                    cube[i][j][k] = value++;
                }
            }
        }

        // 打印三维数组的一个切片
        System.out.println("第一层:");
        for (int j = 0; j < cube[0].length; j++) {
            for (int k = 0; k < cube[0][j].length; k++) {
                System.out.print(cube[0][j][k] + "\t");
            }
            System.out.println();
        }
    }
}

5. 数组工具类 (java.util.Arrays)

java.util.Arrays 类提供了许多静态方法,用于操作数组(如排序、搜索、比较、填充等)。

5.1 常用方法介绍

1. toString() - 数组转字符串

import java.util.Arrays;

public class ArraysToStringExample {
    public static void main(String[] args) {
        int[] numbers = {5, 3, 1, 4, 2};

        // 将数组转换为可读的字符串
        String arrayStr = Arrays.toString(numbers);
        System.out.println("数组字符串表示: " + arrayStr);
        // 输出: [5, 3, 1, 4, 2]

        // 对于多维数组,使用deepToString()
        int[][] matrix = {{1, 2}, {3, 4}};
        System.out.println("二维数组: " + Arrays.deepToString(matrix));
        // 输出: [[1, 2], [3, 4]]
    }
}

2. sort() - 数组排序

import java.util.Arrays;

public class ArraysSortExample {
    public static void main(String[] args) {
        int[] numbers = {5, 3, 1, 4, 2};

        // 升序排序
        Arrays.sort(numbers);
        System.out.println("排序后: " + Arrays.toString(numbers));
        // 输出: [1, 2, 3, 4, 5]

        // 部分排序(对前3个元素排序)
        int[] numbers2 = {5, 3, 1, 4, 2};
        Arrays.sort(numbers2, 0, 3);  // 排序索引0到2(不包括3)
        System.out.println("部分排序: " + Arrays.toString(numbers2));
        // 输出: [1, 3, 5, 4, 2]

        // 字符串数组排序
        String[] names = {"Charlie", "Alice", "Bob"};
        Arrays.sort(names);
        System.out.println("字符串排序: " + Arrays.toString(names));
        // 输出: [Alice, Bob, Charlie]
    }
}

3. binarySearch() - 二分查找

import java.util.Arrays;

public class BinarySearchExample {
    public static void main(String[] args) {
        int[] numbers = {10, 20, 30, 40, 50};

        // 数组必须先排序
        Arrays.sort(numbers);

        // 查找元素
        int index1 = Arrays.binarySearch(numbers, 30);
        System.out.println("30的索引: " + index1);  // 2

        int index2 = Arrays.binarySearch(numbers, 35);
        System.out.println("35的索引: " + index2);  // 负数(未找到)

        // 解释负数返回值:-(插入点) - 1
        // 35应该插入在索引3的位置,所以返回 -4
    }
}

4. fill() - 填充数组

import java.util.Arrays;

public class ArraysFillExample {
    public static void main(String[] args) {
        int[] numbers = new int[5];

        // 用指定值填充整个数组
        Arrays.fill(numbers, 7);
        System.out.println("填充7: " + Arrays.toString(numbers));
        // 输出: [7, 7, 7, 7, 7]

        // 填充部分数组
        int[] numbers2 = new int[5];
        Arrays.fill(numbers2, 1, 4, 9);  // 填充索引1到3(不包括4)
        System.out.println("部分填充: " + Arrays.toString(numbers2));
        // 输出: [0, 9, 9, 9, 0]
    }
}

5. copyOf() 和 copyOfRange() - 复制数组

import java.util.Arrays;

public class ArraysCopyExample {
    public static void main(String[] args) {
        int[] original = {1, 2, 3, 4, 5};

        // 复制整个数组
        int[] copy1 = Arrays.copyOf(original, original.length);
        System.out.println("完整复制: " + Arrays.toString(copy1));

        // 复制前3个元素
        int[] copy2 = Arrays.copyOf(original, 3);
        System.out.println("前3个元素: " + Arrays.toString(copy2));

        // 复制指定范围
        int[] copy3 = Arrays.copyOfRange(original, 1, 4);  // 索引1到3(不包括4)
        System.out.println("范围复制[1,4): " + Arrays.toString(copy3));

        // 扩展数组长度
        int[] extended = Arrays.copyOf(original, 8);
        System.out.println("扩展数组: " + Arrays.toString(extended));
        // 输出: [1, 2, 3, 4, 5, 0, 0, 0]
    }
}

6. equals() 和 deepEquals() - 比较数组

import java.util.Arrays;

public class ArraysEqualsExample {
    public static void main(String[] args) {
        int[] arr1 = {1, 2, 3};
        int[] arr2 = {1, 2, 3};
        int[] arr3 = {1, 2, 4};

        // 比较一维数组
        System.out.println("arr1 equals arr2: " + Arrays.equals(arr1, arr2));  // true
        System.out.println("arr1 equals arr3: " + Arrays.equals(arr1, arr3));  // false

        // 比较二维数组
        int[][] matrix1 = {{1, 2}, {3, 4}};
        int[][] matrix2 = {{1, 2}, {3, 4}};
        int[][] matrix3 = {{1, 2}, {3, 5}};

        System.out.println("matrix1 equals matrix2: " + Arrays.equals(matrix1, matrix2));  // false
        System.out.println("matrix1 deepEquals matrix2: " + Arrays.deepEquals(matrix1, matrix2));  // true
        System.out.println("matrix1 deepEquals matrix3: " + Arrays.deepEquals(matrix1, matrix3));  // false
    }
}

5.2 Arrays 类的其他实用方法

import java.util.Arrays;

public class MoreArraysMethods {
    public static void main(String[] args) {
        // 1. parallelSort() - 并行排序(大数据量时性能更好)
        int[] largeArray = new int[10000];
        // ... 初始化数组
        Arrays.parallelSort(largeArray);

        // 2. parallelPrefix() - 并行前缀计算
        int[] numbers = {1, 2, 3, 4, 5};
        Arrays.parallelPrefix(numbers, (a, b) -> a + b);
        System.out.println("前缀和: " + Arrays.toString(numbers));
        // 输出: [1, 3, 6, 10, 15]

        // 3. setAll() - 使用生成函数设置所有元素
        int[] squares = new int[5];
        Arrays.setAll(squares, i -> (i + 1) * (i + 1));
        System.out.println("平方数组: " + Arrays.toString(squares));
        // 输出: [1, 4, 9, 16, 25]

        // 4. parallelSetAll() - 并行版本
        int[] cubes = new int[5];
        Arrays.parallelSetAll(cubes, i -> (i + 1) * (i + 1) * (i + 1));
        System.out.println("立方数组: " + Arrays.toString(cubes));
        // 输出: [1, 8, 27, 64, 125]
    }
}

6. 数组的常见问题与解决方案

6.1 数组越界 (ArrayIndexOutOfBoundsException)

public class ArrayBoundsExample {
    public static void main(String[] args) {
        int[] numbers = {1, 2, 3};

        try {
            // 尝试访问不存在的索引
            System.out.println("尝试访问numbers[3]: " + numbers[3]);
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("错误: 数组索引越界!");
            System.out.println("有效索引范围: 0 到 " + (numbers.length - 1));
            System.out.println("错误信息: " + e.getMessage());
        }

        // 预防数组越界的正确做法
        int index = 3;
        if (index >= 0 && index < numbers.length) {
            System.out.println("安全访问: numbers[" + index + "] = " + numbers[index]);
        } else {
            System.out.println("索引 " + index + " 超出范围!");
        }
    }
}

6.2 空指针异常 (NullPointerException)

public class NullPointerExample {
    public static void main(String[] args) {
        // 情况1: 数组引用为null
        int[] numbers = null;

        try {
            System.out.println("数组长度: " + numbers.length);
        } catch (NullPointerException e) {
            System.out.println("错误: 数组引用为null!");
        }

        // 情况2: 数组元素为null(对象数组)
        String[] names = new String[3];

        try {
            System.out.println("第一个名字的长度: " + names[0].length());
        } catch (NullPointerException e) {
            System.out.println("错误: 数组元素为null!");
        }

        // 预防空指针异常的正确做法
        if (numbers != null) {
            System.out.println("数组长度: " + numbers.length);
        } else {
            System.out.println("数组未初始化!");
        }

        if (names[0] != null) {
            System.out.println("第一个名字的长度: " + names[0].length());
        } else {
            System.out.println("第一个名字为null!");
        }
    }
}

6.3 数组大小固定问题

import java.util.Arrays;

public class FixedSizeProblem {
    public static void main(String[] args) {
        // 问题: 数组大小固定,无法动态扩展
        int[] numbers = new int[3];
        numbers[0] = 1;
        numbers[1] = 2;
        numbers[2] = 3;

        System.out.println("原始数组: " + Arrays.toString(numbers));

        // 如果需要添加第4个元素,需要创建新数组
        // 解决方案1: 使用Arrays.copyOf()扩展数组
        int[] newNumbers = Arrays.copyOf(numbers, numbers.length * 2);
        newNumbers[3] = 4;
        newNumbers[4] = 5;

        System.out.println("扩展后的数组: " + Arrays.toString(newNumbers));

        // 解决方案2: 使用ArrayList(动态数组)
        // ArrayList<Integer> list = new ArrayList<>();
        // list.add(1);
        // list.add(2);
        // list.add(3);
        // list.add(4); // 可以动态添加
    }
}

6.4 数组与集合的选择

特性 数组 ArrayList(集合)
大小 固定 动态增长
性能 访问快,O(1) 访问快,但插入/删除可能慢
类型安全 编译时类型检查 泛型提供类型安全
内存 连续内存,效率高 需要额外对象开销
功能 基本操作 丰富的方法(add, remove, contains等)

选择建议: - 使用数组:当大小固定且已知,需要最高性能时 - 使用ArrayList:当需要动态大小,频繁添加/删除元素时

7. 数组的实际应用案例

7.1 学生成绩管理系统

import java.util.Arrays;
import java.util.Scanner;

public class GradeManagementSystem {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        System.out.print("请输入学生人数: ");
        int studentCount = scanner.nextInt();

        // 创建二维数组存储成绩:每行代表一个学生,每列代表一门科目
        double[][] grades = new double[studentCount][3]; // 假设有3门科目

        // 输入成绩
        for (int i = 0; i < studentCount; i++) {
            System.out.println("\n--- 输入第 " + (i + 1) + " 个学生的成绩 ---");
            System.out.print("语文成绩: ");
            grades[i][0] = scanner.nextDouble();

            System.out.print("数学成绩: ");
            grades[i][1] = scanner.nextDouble();

            System.out.print("英语成绩: ");
            grades[i][2] = scanner.nextDouble();
        }

        // 计算并显示每个学生的平均分
        System.out.println("\n=== 学生成绩统计 ===");
        for (int i = 0; i < studentCount; i++) {
            double sum = 0;
            for (int j = 0; j < 3; j++) {
                sum += grades[i][j];
            }
            double average = sum / 3;
            System.out.printf("学生 %d: 总分=%.1f, 平均分=%.2f%n", 
                             i + 1, sum, average);
        }

        // 计算每门科目的平均分
        System.out.println("\n=== 科目平均分 ===");
        String[] subjects = {"语文", "数学", "英语"};
        for (int j = 0; j < 3; j++) {
            double sum = 0;
            for (int i = 0; i < studentCount; i++) {
                sum += grades[i][j];
            }
            double subjectAverage = sum / studentCount;
            System.out.printf("%s平均分: %.2f%n", subjects[j], subjectAverage);
        }

        scanner.close();
    }
}

7.2 简单游戏:井字棋

public class TicTacToe {
    private static final int SIZE = 3;
    private static char[][] board = new char[SIZE][SIZE];
    private static char currentPlayer = 'X';

    public static void main(String[] args) {
        initializeBoard();
        printBoard();

        // 简单演示:手动设置一些棋子
        board[0][0] = 'X';
        board[1][1] = 'O';
        board[2][2] = 'X';

        System.out.println("\n游戏进行中...");
        printBoard();

        // 检查是否有赢家
        if (checkWin('X')) {
            System.out.println("玩家 X 获胜!");
        } else if (checkWin('O')) {
            System.out.println("玩家 O 获胜!");
        } else {
            System.out.println("游戏继续...");
        }
    }

    private static void initializeBoard() {
        for (int i = 0; i < SIZE; i++) {
            for (int j = 0; j < SIZE; j++) {
                board[i][j] = '-';
            }
        }
    }

    private static void printBoard() {
        System.out.println("\n当前棋盘:");
        for (int i = 0; i < SIZE; i++) {
            for (int j = 0; j < SIZE; j++) {
                System.out.print(board[i][j] + " ");
            }
            System.out.println();
        }
    }

    private static boolean checkWin(char player) {
        // 检查行
        for (int i = 0; i < SIZE; i++) {
            if (board[i][0] == player && board[i][1] == player && board[i][2] == player) {
                return true;
            }
        }

        // 检查列
        for (int j = 0; j < SIZE; j++) {
            if (board[0][j] == player && board[1][j] == player && board[2][j] == player) {
                return true;
            }
        }

        // 检查对角线
        if (board[0][0] == player && board[1][1] == player && board[2][2] == player) {
            return true;
        }

        if (board[0][2] == player && board[1][1] == player && board[2][0] == player) {
            return true;
        }

        return false;
    }
}

7.3 数组排序算法示例

import java.util.Arrays;

public class SortingAlgorithms {
    public static void main(String[] args) {
        int[] numbers = {64, 34, 25, 12, 22, 11, 90};

        System.out.println("原始数组: " + Arrays.toString(numbers));

        // 1. 冒泡排序
        int[] bubbleSorted = numbers.clone();
        bubbleSort(bubbleSorted);
        System.out.println("冒泡排序: " + Arrays.toString(bubbleSorted));

        // 2. 选择排序
        int[] selectionSorted = numbers.clone();
        selectionSort(selectionSorted);
        System.out.println("选择排序: " + Arrays.toString(selectionSorted));

        // 3. 使用Arrays.sort()
        int[] arraySorted = numbers.clone();
        Arrays.sort(arraySorted);
        System.out.println("Arrays.sort(): " + Arrays.toString(arraySorted));
    }

    // 冒泡排序
    public static void bubbleSort(int[] arr) {
        int n = arr.length;
        for (int i = 0; i < n - 1; i++) {
            for (int j = 0; j < n - i - 1; j++) {
                if (arr[j] > arr[j + 1]) {
                    // 交换 arr[j] 和 arr[j+1]
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }
    }

    // 选择排序
    public static void selectionSort(int[] arr) {
        int n = arr.length;
        for (int i = 0; i < n - 1; i++) {
            int minIndex = i;
            for (int j = i + 1; j < n; j++) {
                if (arr[j] < arr[minIndex]) {
                    minIndex = j;
                }
            }
            // 交换找到的最小元素和第一个未排序位置的元素
            int temp = arr[minIndex];
            arr[minIndex] = arr[i];
            arr[i] = temp;
        }
    }
}

8. 性能优化建议

8.1 数组访问优化

public class ArrayPerformance {
    public static void main(String[] args) {
        int size = 10000;
        int[][] matrix = new int[size][size];

        // 优化前:按列访问(缓存不友好)
        long startTime = System.currentTimeMillis();
        for (int j = 0; j < size; j++) {
            for (int i = 0; i < size; i++) {
                matrix[i][j] = i + j;
            }
        }
        long endTime = System.currentTimeMillis();
        System.out.println("按列访问时间: " + (endTime - startTime) + "ms");

        // 优化后:按行访问(缓存友好)
        startTime = System.currentTimeMillis();
        for (int i = 0; i < size; i++) {
            for (int j = 0; j < size; j++) {
                matrix[i][j] = i + j;
            }
        }
        endTime = System.currentTimeMillis();
        System.out.println("按行访问时间: " + (endTime - startTime) + "ms");
    }
}

8.2 避免不必要的数组复制

public class AvoidUnnecessaryCopy {
    public static void main(String[] args) {
        // 不好的做法:频繁创建新数组
        int[] data = new int[1000];

        // 好的做法:重用数组或使用System.arraycopy()
        int[] buffer = new int[1000];
        // ... 处理数据

        // 需要扩展时,使用合适的增长策略
        int[] expanded = new int[buffer.length * 2];
        System.arraycopy(buffer, 0, expanded, 0, buffer.length);
    }
}

9. 总结

数组是 Java 编程中最基础且重要的数据结构之一。通过本章的学习,你应该掌握:

核心知识点

  1. 数组的基本概念:固定大小、相同类型、连续存储、索引访问
  2. 数组的声明与初始化:多种初始化方式及默认值规则
  3. 数组的访问与遍历:索引访问、多种遍历方法、长度获取
  4. 多维数组:二维数组的创建、初始化、遍历,不规则数组
  5. 数组工具类:Arrays类的常用方法(排序、搜索、复制、比较等)
  6. 常见问题:数组越界、空指针异常、大小固定问题的解决方案
  7. 实际应用:成绩管理、游戏开发、排序算法等案例

最佳实践

  1. 选择合适的结构:根据需求选择数组或集合(如ArrayList)
  2. 注意边界检查:始终验证索引范围,避免数组越界
  3. 合理设计多维数组:根据数据特点选择规则或不规则数组
  4. 利用工具类:优先使用Arrays类提供的方法,避免重复造轮子
  5. 考虑性能:注意访问模式对缓存的影响,避免不必要的数组复制

下一步学习建议

掌握了数组的基础后,建议继续学习: - 集合框架:ArrayList、LinkedList、HashSet等动态数据结构 - 算法基础:基于数组的搜索、排序等算法 - 高级特性:数组与泛型、数组与流(Stream)API的结合使用

数组作为编程的基石,深入理解其原理和用法将为学习更复杂的数据结构和算法打下坚实基础。在实际开发中,根据具体场景灵活运用数组的各种特性,可以编写出高效、可靠的代码。


练习题目: 1. 编写一个程序,找出数组中的最大值和最小值 2. 实现一个方法,将两个数组合并成一个新数组 3. 编写一个程序,统计数组中每个元素出现的次数 4. 实现矩阵的转置操作(行变列,列变行) 5. 编写一个简单的扫雷游戏,使用二维数组表示雷区

通过实践这些练习,可以加深对数组的理解和应用能力。