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