概述
/**
* 解读ArrayList集合中,for循环遍历和迭代器遍历的不同
*
* @author MoCha
* @date 2020/4/3
*/
public class Demo {
public static void main(String[] args) {
ArrayList<Integer> arrayList = new ArrayList<>(Arrays.asList(1, 23, 4, 5));
// An optimized version of AbstractList.ListItr
// 从源码可以看出java.util.ArrayList.ListItr是进行过优化的版本
// 内部继承了java.util.ArrayList.Itr,同时实现了java.util.ListIterator接口
// java.util.ArrayList.ListItr提供更多方法给我们操作集合,比如hasPrevious, add方法
// 所以如果想要在遍历的时候,为ArrayList添加元素,可以使用listIterator()
ListIterator<Integer> integerListIterator = arrayList.listIterator();
while (integerListIterator.hasNext()) {
// integerListIterator.add(1);
// 但凡使用remove操作,都需要先调用next方法,因为remove操作方法是ListIterator继承自java.util.ArrayList.Itr
// 如果不先调用next方法,那么lastRet始终为-1,在调用remove方法时,会抛出IllegalStateException();
integerListIterator.next();
integerListIterator.remove();
if (arrayList.size() < 2) {
break;
}
}
System.out.println(arrayList);
// for循环遍历,实际上用到了next方法,否则,for循环左边的值怎么取的呢
// 而next过程中会判断modCount是否有改变,所以不能在for循环中调用ArrayList的add, remove等方法
// 这些方法,都会使得集合的modCount值发生变化,从而快速失败
// 由debug模式下,调试以下代码可以知道,当第一次进入该循环时,是可以对ArrayList进行添加操作的,
// 不过需要注意的是此时ArrayList的modCount已经发生变化,所以第二次,也就是调用next()方法的时候,检查checkForComodification时出现异常
// 同理,remove也会
// 如果说为什么要用iterator迭代器进行遍历,而不是用for循环来操作
// 最主要的原因是,你无法在for循环里面,对集合的元素进行改动,否则会报异常
// 而使用迭代器的方式,你可以调用ArrayList的listIterator(),而这个java.util.ArrayList.ListItr提供了add, remove方法
for (Integer integer : arrayList) {
// 从源代码可以看出,java.util.ArrayList.add(E)操作是会Increments modCount
// ensureCapacityInternal(size + 1); // Increments modCount!!
arrayList.add(1);
}
System.out.println(arrayList);
}
}
运行结果
[5]
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)
at java.util.ArrayList$Itr.next(ArrayList.java:859)
at top.yangzefeng.movie.Demo.main(Demo.java:43)
总结:
-
for循环中,无法对ArrayList进行改动,否则会出现ConcurrentModificationException
-
如果仅仅只是对ArrayList进行读取遍历,使用forEach会更加简洁
-
如果想要在迭代时对ArrayList进行改动,推荐使用listIterator()方法,该方法返回的java.util.ArrayList.ListItr,继承了ArrayList内部的Itr,实现了ListIterator接口,提供了如hasPrevious, add方法,更加方便我们在遍历时操作ArrayList
-
需要注意的是,在迭代时,不能上来直接就调用remove方法,因为此时lastRet始终为-1,在调用remove方法时,会抛出IllegalStateException();
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();
}
}
最后
以上就是舒心小鸽子为你收集整理的解读ArrayList集合中,for循环遍历和迭代器遍历的不同的全部内容,希望文章能够帮你解决解读ArrayList集合中,for循环遍历和迭代器遍历的不同所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复