Java 中的二維陣列本質上是「陣列的陣列」:外層陣列儲存一維陣列的參考,每個一維陣列長度可以不同 (不規則陣列/Jagged Array)。
public class ArrayDemo1 {
public static void main(String[] args) {
float[][] matrix; // 1. 宣告變數
matrix = new float[5][5]; // 2. 配置 5x5 空間
// 3. 逐一賦值 (索引從 0 開始)
matrix[0][0] = 1.1f;
matrix[1][0] = 1.2f;
matrix[2][0] = 1.3f;
matrix[3][0] = 1.4f;
matrix[4][0] = 1.5f;
// 輸出驗證
for (int i = 0; i < 5; i++) {
System.out.println("matrix[" + i + "][0] = " + matrix[i][0]);
}
}
}
特點:步驟明確,適合動態決定維度大小的情況。
public class ArrayDemo2 {
public static void main(String[] args) {
// 宣告並配置 5 列 8 行
short[][] matrix = new short[5][8];
matrix[0][7] = 10;
matrix[1][6] = 20;
matrix[2][5] = 30;
matrix[3][4] = 40;
matrix[4][3] = 50;
// 輸出
System.out.println(matrix[0][7]); // 10
System.out.println(matrix[4][3]); // 50
}
}
特點:最常用寫法,適用於規則矩形陣列。
public class ArrayDemo3 {
public static void main(String[] args) {
// 宣告 5 列,每列長度暫不指定
long[][] jagged = new long[5][];
// 逐列配置不同長度
jagged[0] = new long[5];
jagged[1] = new long[6];
jagged[2] = new long[7];
jagged[3] = new long[8];
jagged[4] = new long[9];
// 賦值
jagged[0][4] = 10_000_000_000L;
jagged[1][5] = 20_000_000_000L;
jagged[2][6] = 30_000_000_000L;
jagged[3][7] = 40_000_000_000L;
jagged[4][8] = 50_000_000_000L;
// 未賦值元素自動初始為 0
System.out.println("jagged[4][7] = " + jagged[4][7]); // 0
}
}
特點:節省記憶體,適合三角矩陣、稀疏矩陣等非矩形資料結構。
public class ArrayDemo4 {
public static void main(String[] args) {
// 宣告同時賦值:2 列 3 行
double[][] matrix = {
{1.111, 2.222, 3.333},
{4.444, 5.555, 6.666}
};
System.out.println(matrix[0][0]); // 1.111
System.out.println(matrix[1][1]); // 5.555
System.out.println("列數: " + matrix.length); // 2
System.out.println("行數: " + matrix[0].length); // 3
}
}
特點:資料固定已知時最簡潔,編譯器自動推導維度。
public class ArrayDemo5 {
public static void main(String[] args) {
int[][] jagged = {
{10, 20, 30}, // 第 0 列:3 個元素
{40, 50}, // 第 1 列:2 個元素
{60} // 第 2 列:1 個元素
};
System.out.println(jagged[0][2]); // 30
System.out.println(jagged[1][1]); // 50
System.out.println(jagged[2][0]); // 60
}
}
特點:直觀表達不規則結構,常用於 Pascal 三角形、動態規劃 DP 表等。
public class ArrayDemo6 {
public static void main(String[] args) {
// 匿名陣列直接賦值給變數
int[][] matrix = new int[][] {
{100, 200, 300, 400},
{500, 600, 700, 800},
{900, 1000, 1100, 1200, 1300} // 第 2 列有 5 個元素
};
System.out.println(matrix[0][2]); // 300
System.out.println(matrix[1][2]); // 700
System.out.println(matrix[2][1]); // 1000
}
}
特點:語法上明確表達「建立新陣列實例」,可用於方法參數傳遞:method(new int[][]{{1,2},{3,4}})。
int[][] arr = new int[3][4];
arr.length; // 3 (外層陣列長度 = 列數)
arr[0].length; // 4 (第一列長度 = 行數)
arr[1].length; // 4 (第二列長度)
// 不規則陣列每列長度可能不同
int[][] jagged = {{1,2}, {3,4,5}, {6}};
jagged[0].length; // 2
jagged[1].length; // 3
jagged[2].length; // 1
// 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 迴圈 (推薦)
for (int[] row : matrix) {
for (int val : row) {
System.out.print(val + " ");
}
System.out.println();
}
// 3. Java 8 Stream (函數式)
Arrays.stream(matrix)
.flatMapToInt(Arrays::stream)
.forEach(val -> System.out.print(val + " "));
int[][] src = {{1,2}, {3,4}};
// 淺層複製 (只複製參考,修改會影響原陣列)
int[][] shallow = src.clone();
int[][] shallow2 = Arrays.copyOf(src, src.length);
// 深層複製 (完全獨立)
int[][] deep = new int[src.length][];
for (int i = 0; i < src.length; i++) {
deep[i] = Arrays.copyOf(src[i], src[i].length);
}
// 或 Java 8+
int[][] deep2 = Arrays.stream(src).map(row -> row.clone()).toArray(int[][]::new);
| 錯誤代碼 | 問題 | 正確寫法 |
|---|---|---|
| int[][] a = new int[][]; | 缺少第一維大小 | new int[3][] 或 new int[3][4] |
| int[][] a = new int[3][4]; a[3][0]=1; | 索引越界 (0~2) | a[2][0]=1 |
| int[][] a = {{1,2}, {3}}; a[1][2]=9; | 第二列長度只有 2 | 檢查 a[1].length |
| int[] a = new int[3][3]; | 型別不匹配 | int[][] a = ... |
| 傳遞二維陣列給方法修改長度 | Java 傳值呼叫,無法改變外層參考 | 回傳新陣列或使用 List<List<Integer>> |
public static int[][] multiply(int[][] a, int[][] b) {
int rowsA = a.length, colsA = a[0].length;
int colsB = b[0].length;
int[][] result = new int[rowsA][colsB];
for (int i = 0; i < rowsA; i++) {
for (int j = 0; j < colsB; j++) {
for (int k = 0; k < colsA; k++) {
result[i][j] += a[i][k] * b[k][j];
}
}
}
return result;
}
public static int lcs(String s1, String s2) {
int m = s1.length(), n = s2.length();
int[][] dp = new int[m + 1][n + 1]; // 不規則邊界自動處理
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
if (s1.charAt(i-1) == s2.charAt(j-1)) {
dp[i][j] = dp[i-1][j-1] + 1;
} else {
dp[i][j] = Math.max(dp[i-1][j], dp[i][j-1]);
}
}
}
return dp[m][n];
}
// 無向圖
int V = 5; // 頂點數
int[][] adj = new int[V][V];
adj[0][1] = adj[1][0] = 1; // 邊 0-1
adj[0][2] = adj[2][0] = 1; // 邊 0-2
// 稀疏圖建議改用鄰接表 List<List<Integer>>
掌握六種二維陣列初始化寫法,關鍵在於理解「陣列的陣列」本質。規則資料用矩形陣列 (寫法二、四),不規則資料用鋸齒陣列 (寫法三、五)。現代開發中,複雜資料結構建議優先考慮 List<List<T>> 或專用資料結構庫 (如 Apache Commons Math、ND4J),獲得更好的彈性與功能支援。