for循環直接刪除ArrayList中的特定元素是錯的,不同的for循環會發生不同的錯誤,泛型for會拋出 ConcurrentModificationException,普通的for想要刪除集合中重復且連續的元素,只能刪除第一個。
錯誤原因:打開JDK的ArrayList源碼,看下ArrayList中的remove方法(注意ArrayList中的remove有兩個同名方法,只是入參不同,這里看的是入參為Object的remove方法)是怎么實現的,一般情況下程序的執行路徑會走到else路徑下最終調用faseRemove方法,會執行System.arraycopy方法,導致刪除元素時涉及到數組元素的移動。針對普通for循環的錯誤寫法,在遍歷第一個字符串b時因為符合刪除條件,所以將該元素從數組中刪除,並且將后一個元素移動(也就是第二個字符串b)至當前位置,導致下一次循環遍歷時后一個字符串b並沒有遍歷到,所以無法刪除。針對這種情況可以倒序刪除的方式來避免。
public boolean remove(Object o) { if (o == null) { for (int index = 0; index < size; index++) if (elementData[index] == null) { fastRemove(index); return true; } } else { for (int index = 0; index < size; index++) if (o.equals(elementData[index])) { fastRemove(index); return true; } } return false; } private void fastRemove(int index) { modCount++; int numMoved = size - index - 1; if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); elementData[--size] = null; // clear to let GC do its work }
解決方案:用 Iterator:
public static void main(String[] args) { List<String> list = new ArrayList<>(Arrays.asList("a", "b" , "c", "d")); Iterator<String> iterator = list.iterator(); while (iterator.hasNext()) { if(iterator.next().equals("b")) { iterator.remove(); } } System.out.println(list); }
輸出結果:a, c, d