我是靠谱客的博主 完美啤酒,这篇文章主要介绍foreach与iterator总结,现在分享给大家,希望可以做个参考。

1.foreach

执行下面这段代码的时候会抛出异常

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
public void testForeach() { List<Integer> list = new ArrayList<>(); for (int i = 0; i < 10; i++) { list.add(i); } //foreach for (Integer integer : list) { if (integer == 6) { list.remove(integer); } } }

java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
    at java.util.ArrayList$Itr.next(ArrayList.java:851)

然后跟踪到错误源,发现ArrayList中的iterator中有expectedModCount和modCount两个值,初始化的时候默认相等。

复制代码
1
2
3
4
5
6
7
8
9
10
public Iterator<E> iterator() { return new Itr(); } private class Itr implements Iterator<E> { int cursor; // index of next element to return int lastRet = -1; // index of last element returned; -1 if no such int expectedModCount = modCount; ... }

执行到list.remove(integer)的时候,remove方法进入到fastRemove方法,然后modCount的值改变了。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public boolean remove(Object o) { if (o == null) { for (int index = 0; index < size; index++) if (elementData[index] == null) { fastRemove(index); return true; } } else { for (int index = 0; index < size; index++) if (o.equals(elementData[index])) { fastRemove(index); return true; } } return false; } private void fastRemove(int index) { modCount++; int numMoved = size - index - 1; if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); elementData[--size] = null; // clear to let GC do its work }

继续循环遍历的时候会用到iterator中的next方法,其中checkForComodification()会检查expectedModCount和modCount的值是不是相等,不相等则抛出异常。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public E next() { checkForComodification(); int i = cursor; if (i >= size) throw new NoSuchElementException(); Object[] elementData = ArrayList.this.elementData; if (i >= elementData.length) throw new ConcurrentModificationException(); cursor = i + 1; return (E) elementData[lastRet = i]; } final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); }

2.iterator

执行下面这段代码,输出结果为9。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public void testIterator() { List<Integer> list = new ArrayList<>(); for (int i = 0; i < 10; i++) { list.add(i); } //Iterator Iterator iterator = list.iterator(); while (iterator.hasNext()) { Integer integer = (Integer) iterator.next(); if (integer == 6) { iterator.remove(); } } System.out.println(list.size()); }

查看源码,当使用iterator.remove()的时候,删除完后会执行expectedModCount = modCount,所以不会抛出异常。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
private class Itr implements Iterator<E> { ... 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(); } ... }

总结

1.使用foreach循环遍历,其实是内部调用迭代器实现,迭代器中会有expectedModCount、modCount两个值,如果两个值不相等,在遍历的时候会抛异常。

2.集合和iterator的remove方法是有区别的,iterator的remove删除后会使expectedModCount = modCount,而集合的remove没有,所以在中foreach中使用集合的remove时,再次遍历的时候会抛异常。

3.for循环不涉及iterator,故可以直接删除集合中的元素。

最后

以上就是完美啤酒最近收集整理的关于foreach与iterator总结的全部内容,更多相关foreach与iterator总结内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(57)

评论列表共有 0 条评论

立即
投稿
返回
顶部