经过测试,发现对于一个集合,如果要在遍历的过程中,进行add或者remove操作的时候,如果操作不慎,都会导致报错。
主要错误:
-
java.util.ConcurrentModificationException 遍历过程中add/remove导致的错误
-
java.lang.IndexOutOfBoundsException 越界错误
最佳实践
add操作:利用原生的for循环。remove操作利用foreach操作。如下所示:
//OK,利用 iterator 和 其remove 方法
经典错误1
如下代码本意是:通过iterator的方式从头到尾变遍历list中的元素。
但是该段代码永远都会输出 list的第一元素,为什么?关键错误在链式写法上:
while (list.iterator().hasNext()) {}
每次循环时候先调用了list.iterator()
在该方法中每次都是重新new
了一个新的对象
public Iterator<E> iterator() {
return new Itr();
}
所以每一次都是一个新的遍历对象,所以输出第一个元素。
那么为什么每次都要new一个新的Itr()
?我猜想应该是为了并发的读,每次读的都是一份独立的数据,避免多个并发读的时候,出现当前指针问题。
处理办法:将list.iteraotr()
放在外面即可,保证循环中循环的是1个对象。
经典错误2
// 死循环
当if条件满足的时候,该方法永远不会结束,为什么?
对于for循环 for (int i = 0; i < list.size(); i++)
有3个部分,第一个部分为初始化,只执行一次。第二个部分每次都会执行,第三个部分也是每次都会执行。
上述问题的第二步会导致无限循环:因为for中每一次循环都会在list添加了一个元素,每次步进为1,内部元素也是每次都加1.
如何处理该问题: list.size()
放在第一部分,第一部分只初始化一次。
//OK 利用for循环。
经典错误3
//java.lang.IndexOutOfBoundsException: Index: 2, Size: 2
该错误在list.add("3")
的时候就不会发生该错误,具体原因是什么?