首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

ArrayList 刪除陷阱:正向遍歷刪除導致索引錯位

     編輯:Java 相關知識

陷阱代碼


ArrayList strAl = new ArrayList<>();
strAl.add("a"); strAl.add("b"); strAl.add("c"); strAl.add("d"); // [a,b,c,d]

ArrayList indexes = new ArrayList<>();
indexes.add(0); indexes.add(2);  // 要刪除索引 0 和 2

for (int i = 0; i < indexes.size(); i++) {
    strAl.remove(indexes.get(i));  // 陷阱在這裡!
}
System.out.println(strAl.size());  // 輸出多少?

運行結果

輸出:3(預期 2)

最終列表:[b, c, d] → 實際只刪除了 a,c 倖免。

原理圖解

步驟操作列表變化索引映射
初始-[a, b, c, d]0:a, 1:b, 2:c, 3:d
i=0remove(0)[b, c, d]原 1→新 0, 原 2→新 1, 原 3→新 2
i=1remove(2)[b, c]刪除的是「新索引 2」即原 d,而非原 c!

核心原因:ArrayList.remove(int index) 會將後續元素前移填補空位,導致原索引失效。正向遍歷時,後續要刪除的索引未同步更新,刪錯元素。

三種正確解法

1. 逆向遍歷(最推薦,O(1) 空間)


for (int i = indexes.size() - 1; i >= 0; i--) {
    strAl.remove(indexes.get(i));
}
// 先刪大索引,不影響小索引位置

2. 收集要刪除的元素,批量 removeAll(語義清晰)


List toRemove = new ArrayList<>();
for (Integer idx : indexes) {
    if (idx >= 0 && idx < strAl.size()) toRemove.add(strAl.get(idx));
}
strAl.removeAll(toRemove);

3. 使用 Iterator 刪除(單次遍歷場景)


Iterator it = strAl.iterator();
while (it.hasNext()) {
    String s = it.next();
    if (需刪除條件) it.remove();  // 安全刪除當前元素
}

延伸:LinkedList 同樣受影響

LinkedList.remove(int index) 同樣會改變後續節點的索引位置,**同樣存在此陷阱**。逆向遍歷同樣有效。

總結

  • 正向遍歷 + 刪除 = 索引錯位 Bug。
  • 養成逆向遍歷刪除習慣,或用 removeAll/Iterator。
  • 面試高頻考點,必會!
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved