对List遍历过程当中添加和删除的思考

对List遍历过程当中添加和删除的思考java

平时开发过程当中,很多开发者都遇到过一个问题:在遍历集合的的过程当中,进行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");
}
}
}
经典错误3rem

//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!get

相关文章
相关标签/搜索