新手寫雙層循環比較兩個陣列,明明邏輯似乎通順,結果卻全是 0。問題出在哪?本文通過一個典型錯誤案例,揭示陣列索引混淆、賦值邏輯反轉、循環邊界錯誤三大塹坑,並給出正確重構代碼。
String[] a = {"0","1"};
String[][] b = {
{"第一個元素","第二個元素","第三個元素","第四個元素"},
{"4","5","6","1"}
};
for(int x = 0; x < a.length; x++) {
for(int w = 0; w < b.length; w++) {
if(a[x].equals(b[x+1][w])) { // 💥 陷阱 1:x+1 導致索引越界
b[x+1][w] = "1"; // 💥 陷阱 2:修改的是 b 的第二行,而非標記結果
break;
} else {
b[x+1][w] = "0"; // 💥 陷阱 3:else 分支會把同一行後續元素全部覆蓋為 0
}
}
}
b[x+1][w] 當 x=1 時訪問 b[2] 不存在a.length=2,x 取值 0、1。b.length=2(兩行),合法行索引 0、1。x+1 導致第二輪訪問 b[2] → ArrayIndexOutOfBoundsException 或未定義行為。
題目要求「相同為 1,不同為 0」,應產出新結果陣列或標記位,不能覆蓋原始數據 b。
else 分支破壞已匹配標記內層循環中,一旦某 w 不匹配就執行 b[x+1][w]="0",導致後續即使找到匹配也被覆蓋。正確邏輯:預設全 0,找到匹配設 1 並 break。
String[] a = {"0", "1"};
String[][] b = {
{"第一個元素", "第二個元素", "第三個元素", "第四個元素"},
{"4", "5", "6", "1"}
};
// 結果陣列:與 b 結構一致,存放 0/1 標記
String[][] result = new String[b.length][b[0].length];
for (int i = 0; i < a.length; i++) {
// 預設本行全為 0
Arrays.fill(result[i], "0");
for (int j = 0; j < b[i].length; j++) { // 修正:遍歷 b 的第 i 行
if (a[i].equals(b[i][j])) { // 修正:比較對應行
result[i][j] = "1"; // 標記匹配位置
break; // 找到即停止
}
}
}
// 輸出驗證
for (String[] row : result) {
System.out.println(Arrays.toString(row));
}
// 輸出:
// [0, 0, 0, 0] // 第 0 行無 "0"
// [0, 0, 0, 1] // 第 1 行第 3 索引匹配 "1"
b 只讀,結果寫入獨立 result。a[i] 對應 b[i] 行,而非 b[x+1]。Arrays.fill(row, "0"),匹配成功設 "1" 並 break。j < b[i].length 防越界。String[][] result = IntStream.range(0, a.length)
.mapToObj(i -> Arrays.stream(b[i])
.map(val -> a[i].equals(val) ? "1" : "0")
.toArray(String[]::new))
.toArray(String[][]::new);
陣列操作看似簡單,實則暗藏索引、邊界、副作用等陷阱。養成「先定義結果結構、再填充、最後輸出」的三步走習慣,配合單元測試驗證邊界情況,即可避開 90% 的低級錯誤。