第19章

Java多维数组

掌握二维数组和多维数组的使用方法与实战应用

学习目标

多维数组概念

多维数组是数组的数组,最常见的是二维数组。在Java中,多维数组实际上是一维数组,其中每个元素都是另一个数组的引用。这种结构特别适合处理表格数据、矩阵运算、游戏地图等场景。

重要概念:Java中的多维数组是"数组的数组",而不是真正的多维数组。这意味着每一行可以有不同的长度,形成不规则数组。

二维数组

声明语法:
// 方式1:推荐
int[][] matrix = new int[3][4];

// 方式2:C风格
int matrix[][] = new int[3][4];

// 方式3:混合风格
int[] matrix[] = new int[3][4];
  • 表示行和列的二维结构
  • 适合处理表格数据
  • 常用于矩阵运算
  • 游戏地图和棋盘表示

三维数组

声明语法:
// 三维数组声明
int[][][] cube = new int[2][3][4];

// 表示:2个3x4的矩阵
// 可以理解为2层楼,每层3行4列
  • 三个维度的数据结构
  • 适合3D图形处理
  • 多层数据存储
  • 复杂数据模型表示

二维数组详解

创建和初始化

二维数组的创建方式:
// 1. 指定大小后赋值
int[][] matrix1 = new int[3][4];
matrix1[0][0] = 1;
matrix1[0][1] = 2;

// 2. 创建时初始化
int[][] matrix2 = {
    {1, 2, 3, 4},
    {5, 6, 7, 8},
    {9, 10, 11, 12}
};

// 3. 使用new关键字初始化
int[][] matrix3 = new int[][]{
    {1, 2, 3},
    {4, 5, 6},
    {7, 8, 9}
};

// 4. 不规则数组(锯齿数组)
int[][] jaggedArray = {
    {1, 2},
    {3, 4, 5, 6},
    {7, 8, 9}
};

二维数组可视化(3x3矩阵)

1
2
3
4
5
6
7
8
9

matrix[行][列] - 例如:matrix[1][2] = 6

遍历多维数组

多种遍历方式:
int[][] matrix = {
    {1, 2, 3},
    {4, 5, 6},
    {7, 8, 9}
};

// 1. 传统for循环遍历
System.out.println("方式1:传统for循环");
for (int i = 0; i < matrix.length; i++) {
    for (int j = 0; j < matrix[i].length; j++) {
        System.out.print(matrix[i][j] + " ");
    }
    System.out.println();
}

// 2. 增强for循环遍历
System.out.println("\n方式2:增强for循环");
for (int[] row : matrix) {
    for (int element : row) {
        System.out.print(element + " ");
    }
    System.out.println();
}

// 3. 使用Arrays.deepToString()打印
System.out.println("\n方式3:Arrays.deepToString()");
System.out.println(Arrays.deepToString(matrix));

实际应用案例

矩阵运算

矩阵加法示例:
public class MatrixOperations {
    
    // 矩阵加法
    public static int[][] addMatrices(int[][] a, int[][] b) {
        if (a.length != b.length || a[0].length != b[0].length) {
            throw new IllegalArgumentException("矩阵维度不匹配");
        }
        
        int rows = a.length;
        int cols = a[0].length;
        int[][] result = new int[rows][cols];
        
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                result[i][j] = a[i][j] + b[i][j];
            }
        }
        
        return result;
    }
    
    // 矩阵转置
    public static int[][] transpose(int[][] matrix) {
        int rows = matrix.length;
        int cols = matrix[0].length;
        int[][] result = new int[cols][rows];
        
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                result[j][i] = matrix[i][j];
            }
        }
        
        return result;
    }
}

游戏地图表示

简单游戏地图:
public class GameMap {
    private static final int EMPTY = 0;
    private static final int WALL = 1;
    private static final int PLAYER = 2;
    private static final int TREASURE = 3;
    
    private int[][] map = {
        {1, 1, 1, 1, 1},
        {1, 2, 0, 0, 1},
        {1, 0, 1, 0, 1},
        {1, 0, 0, 3, 1},
        {1, 1, 1, 1, 1}
    };
    
    public void printMap() {
        String[] symbols = {" ", "█", "P", "T"};
        
        for (int[] row : map) {
            for (int cell : row) {
                System.out.print(symbols[cell] + " ");
            }
            System.out.println();
        }
    }
    
    public boolean movePlayer(int newRow, int newCol) {
        // 查找当前玩家位置
        int[] playerPos = findPlayer();
        if (playerPos == null) return false;
        
        // 检查新位置是否有效
        if (isValidMove(newRow, newCol)) {
            map[playerPos[0]][playerPos[1]] = EMPTY;
            map[newRow][newCol] = PLAYER;
            return true;
        }
        
        return false;
    }
    
    private int[] findPlayer() {
        for (int i = 0; i < map.length; i++) {
            for (int j = 0; j < map[i].length; j++) {
                if (map[i][j] == PLAYER) {
                    return new int[]{i, j};
                }
            }
        }
        return null;
    }
    
    private boolean isValidMove(int row, int col) {
        return row >= 0 && row < map.length && 
               col >= 0 && col < map[0].length && 
               map[row][col] != WALL;
    }
}

不规则数组(锯齿数组)

Java允许创建不规则数组,即每一行可以有不同的长度。这在某些场景下非常有用,比如存储不同长度的数据集合。

不规则数组示例:
public class JaggedArrayExample {
    public static void main(String[] args) {
        // 创建不规则数组
        int[][] jaggedArray = new int[4][];
        
        // 为每一行分配不同长度的数组
        jaggedArray[0] = new int[1];  // 第1行:1个元素
        jaggedArray[1] = new int[2];  // 第2行:2个元素
        jaggedArray[2] = new int[3];  // 第3行:3个元素
        jaggedArray[3] = new int[4];  // 第4行:4个元素
        
        // 填充数据
        int value = 1;
        for (int i = 0; i < jaggedArray.length; i++) {
            for (int j = 0; j < jaggedArray[i].length; j++) {
                jaggedArray[i][j] = value++;
            }
        }
        
        // 打印不规则数组
        System.out.println("不规则数组:");
        for (int i = 0; i < jaggedArray.length; i++) {
            for (int j = 0; j < jaggedArray[i].length; j++) {
                System.out.print(jaggedArray[i][j] + " ");
            }
            System.out.println();
        }
        
        // 直接初始化不规则数组
        String[][] studentGrades = {
            {"张三", "85", "92", "78"},           // 3门课程
            {"李四", "90", "88"},                 // 2门课程
            {"王五", "76", "82", "91", "85"}      // 4门课程
        };
        
        System.out.println("\n学生成绩:");
        for (String[] student : studentGrades) {
            System.out.print(student[0] + ": ");
            for (int i = 1; i < student.length; i++) {
                System.out.print(student[i] + " ");
            }
            System.out.println();
        }
    }
}
注意:使用不规则数组时,要特别注意每一行的长度可能不同,避免数组越界异常。始终使用 array[i].length 来获取当前行的长度。

性能优化与最佳实践

多维数组最佳实践

推荐做法

  • 合理选择维度:根据实际需求选择合适的维度,避免过度复杂化
  • 初始化时指定大小:提前知道大小时,一次性分配内存
  • 使用增强for循环:遍历时优先使用增强for循环,代码更简洁
  • 边界检查:访问数组元素前进行边界检查
  • 缓存数组长度:在循环中缓存array.length避免重复计算

避免做法

  • 过深的嵌套:避免创建过多维度的数组,影响可读性
  • 忽略null检查:不检查数组或子数组是否为null
  • 硬编码索引:避免在代码中硬编码数组索引
  • 内存浪费:创建过大的数组而实际使用很少
  • 频繁重新分配:在循环中频繁创建新数组
性能优化示例:
public class ArrayPerformance {
    
    // 好的做法:缓存数组长度
    public static void efficientTraversal(int[][] matrix) {
        int rows = matrix.length;  // 缓存行数
        
        for (int i = 0; i < rows; i++) {
            int cols = matrix[i].length;  // 缓存列数
            for (int j = 0; j < cols; j++) {
                // 处理 matrix[i][j]
                System.out.print(matrix[i][j] + " ");
            }
            System.out.println();
        }
    }
    
    // 安全的数组访问
    public static int safeGet(int[][] matrix, int row, int col) {
        if (matrix == null || row < 0 || row >= matrix.length) {
            throw new IndexOutOfBoundsException("行索引越界");
        }
        
        if (matrix[row] == null || col < 0 || col >= matrix[row].length) {
            throw new IndexOutOfBoundsException("列索引越界");
        }
        
        return matrix[row][col];
    }
    
    // 内存友好的矩阵创建
    public static int[][] createMatrix(int rows, int cols, int defaultValue) {
        int[][] matrix = new int[rows][cols];
        
        // 如果默认值不是0,才需要初始化
        if (defaultValue != 0) {
            for (int i = 0; i < rows; i++) {
                Arrays.fill(matrix[i], defaultValue);
            }
        }
        
        return matrix;
    }
}

完整代码示例

多维数组综合示例:
import java.util.Arrays;
import java.util.Scanner;

public class MultidimensionalArrayDemo {
    
    public static void main(String[] args) {
        // 1. 基本二维数组操作
        demonstrateBasicOperations();
        
        // 2. 矩阵运算
        demonstrateMatrixOperations();
        
        // 3. 不规则数组
        demonstrateJaggedArray();
        
        // 4. 实际应用:学生成绩管理
        demonstrateGradeManagement();
    }
    
    private static void demonstrateBasicOperations() {
        System.out.println("=== 基本二维数组操作 ===");
        
        // 创建和初始化
        int[][] matrix = {
            {1, 2, 3},
            {4, 5, 6},
            {7, 8, 9}
        };
        
        System.out.println("原始矩阵:");
        printMatrix(matrix);
        
        // 修改元素
        matrix[1][1] = 50;
        System.out.println("\n修改后的矩阵:");
        printMatrix(matrix);
        
        // 获取矩阵信息
        System.out.println("\n矩阵信息:");
        System.out.println("行数: " + matrix.length);
        System.out.println("列数: " + matrix[0].length);
        System.out.println("总元素数: " + (matrix.length * matrix[0].length));
    }
    
    private static void demonstrateMatrixOperations() {
        System.out.println("\n=== 矩阵运算 ===");
        
        int[][] a = {{1, 2}, {3, 4}};
        int[][] b = {{5, 6}, {7, 8}};
        
        System.out.println("矩阵A:");
        printMatrix(a);
        
        System.out.println("\n矩阵B:");
        printMatrix(b);
        
        // 矩阵加法
        int[][] sum = addMatrices(a, b);
        System.out.println("\nA + B =");
        printMatrix(sum);
        
        // 矩阵转置
        int[][] transposed = transpose(a);
        System.out.println("\nA的转置:");
        printMatrix(transposed);
    }
    
    private static void demonstrateJaggedArray() {
        System.out.println("\n=== 不规则数组 ===");
        
        // 创建三角形数组
        int[][] triangle = new int[5][];
        for (int i = 0; i < triangle.length; i++) {
            triangle[i] = new int[i + 1];
            for (int j = 0; j <= i; j++) {
                triangle[i][j] = i + j + 1;
            }
        }
        
        System.out.println("三角形数组:");
        for (int[] row : triangle) {
            for (int element : row) {
                System.out.printf("%3d ", element);
            }
            System.out.println();
        }
    }
    
    private static void demonstrateGradeManagement() {
        System.out.println("\n=== 学生成绩管理 ===");
        
        // 学生成绩:3个学生,4门课程
        double[][] grades = {
            {85.5, 92.0, 78.5, 88.0},  // 学生1
            {90.0, 87.5, 91.0, 89.5},  // 学生2
            {76.0, 82.5, 85.0, 79.5}   // 学生3
        };
        
        String[] students = {"张三", "李四", "王五"};
        String[] subjects = {"数学", "英语", "物理", "化学"};
        
        // 打印成绩表
        System.out.printf("%-6s", "学生");
        for (String subject : subjects) {
            System.out.printf("%8s", subject);
        }
        System.out.printf("%8s\n", "平均分");
        
        for (int i = 0; i < students.length; i++) {
            System.out.printf("%-6s", students[i]);
            double sum = 0;
            for (int j = 0; j < grades[i].length; j++) {
                System.out.printf("%8.1f", grades[i][j]);
                sum += grades[i][j];
            }
            double average = sum / grades[i].length;
            System.out.printf("%8.1f\n", average);
        }
        
        // 计算每门课程的平均分
        System.out.println("\n各科平均分:");
        for (int j = 0; j < subjects.length; j++) {
            double sum = 0;
            for (int i = 0; i < students.length; i++) {
                sum += grades[i][j];
            }
            double average = sum / students.length;
            System.out.printf("%s: %.1f\n", subjects[j], average);
        }
    }
    
    // 工具方法:打印矩阵
    private static void printMatrix(int[][] matrix) {
        for (int[] row : matrix) {
            for (int element : row) {
                System.out.printf("%4d", element);
            }
            System.out.println();
        }
    }
    
    // 工具方法:矩阵加法
    private static int[][] addMatrices(int[][] a, int[][] b) {
        int rows = a.length;
        int cols = a[0].length;
        int[][] result = new int[rows][cols];
        
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                result[i][j] = a[i][j] + b[i][j];
            }
        }
        
        return result;
    }
    
    // 工具方法:矩阵转置
    private static int[][] transpose(int[][] matrix) {
        int rows = matrix.length;
        int cols = matrix[0].length;
        int[][] result = new int[cols][rows];
        
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                result[j][i] = matrix[i][j];
            }
        }
        
        return result;
    }
}
💻 查看完整代码 - 在线IDE体验

章节总结