List循环删除元素
list循环有条件删除是,一般会有下边三种思路。
1.foreach循环
public static void main(String[] args) {
List<String> arrayList = new ArrayList();
arrayList.add("aaa");
arrayList.add("aaa");
arrayList.add("bbb");
arrayList.add("ccc");
for (String item : arrayList
) {
if (item.equals("aaa")) {
arrayList.remove(item);
}
}
}
报错:java.util.ConcurrentModificationException.
原因:foreach循环其实是迭代器循环,删除调用的是外部的remove,修改了list的modcount。触发list迭代器代码,如下
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
2.fori循环
public static void main(String[] args) {
List<String> arrayList = new ArrayList();
arrayList.add("aaa");
arrayList.add("aaa");
arrayList.add("bbb");
arrayList.add("ccc");
for (int i = 0; i < arrayList.size(); i++) {
String s = arrayList.get(i);
if (s.equals("aaa")) {
arrayList.remove(i);
}
}
System.err.println(arrayList);
}
结果 :[aaa, bbb, ccc]
为啥少删一个呢,当删完第一个aaa时,list变为[aaa, bbb, ccc],此时i为1,所以进入循环体的时候检验的是arrayList.get(1),也就是bbb。
解决: 在remove之后加个i–;
3.Iterator循环(正确打开方式)
public static void main(String[] args) {
List<String> arrayList = new ArrayList();
arrayList.add("aaa");
arrayList.add("aaa");
arrayList.add("bbb");
arrayList.add("ccc");
Iterator<String> iterator = arrayList.iterator();
while (iterator.hasNext()) {
if (iterator.next().equals("aaa")) {
iterator.remove();
}
}
System.err.println(arrayList);
}
调用迭代器,且使用迭代器内部的删除(其实就是fori里边的删除方法),使得
modCount与expectedModCount同步变化
源码如下:ArrayList.this.remove(lastRet);之后,有expectedModCount = modCount;操作
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}