我是靠谱客的博主 热情砖头,这篇文章主要介绍使用增强for遍历集合时,删除元素是如何抛出异常的?,现在分享给大家,希望可以做个参考。

看如下代码:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add("aaa"); list.add("bbb"); list.add("ccc"); for (String name : list) { System.out.println(name); if ("ccc".equals(name)) { list.remove(name); } } }

看一下抛出的异常信息:

remove()方法并不会抛出异常,抛出异常的是Itr的next方法!!但是remove()方法会导致Itr.next()发生异常。

 Itr是ArrayList的一个内部迭代器类,增强for实际上调用的就是这个迭代器的代码!看下这两个方法的代码:

复制代码
1
2
3
4
public boolean remove(Object o) { modCount++;//就是这个变量(修改次数)和异常的发生有密切关系!! ... }

再看下Itr的代码:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private class Itr implements Iterator<E> { int expectedModCount = modCount;//这里是初始化赋值 Itr() {} public E next() { checkForComodification(); ... } final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); } }

当使用增强for遍历时,会new Itr(),在初始化对象的时候expectedModCount就已经被modCount初始化确定了!!所以调用了remove()方法会使modCount++。导致expectedModCount、modCount不相等!这样再取下一个元素next()的时候,就会被检查出不相等,导致程序抛出ConcurrentModificationException异常。

补充:

1、我们直接使用ArrayList的迭代器,其实用的也是Itr类对象。所以直接用增强for会更方便!

复制代码
1
2
3
4
5
Iterator<String> iterator = list.iterator(); public Iterator<E> iterator() { return new Itr(); }

2、使用增强for遍历时,删除list中的倒数第二个元素,不会抛出ConcurrentModificationException异常。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
List<String> list = new ArrayList<>(); list.add("aaa"); list.add("bbb"); list.add("ccc"); for (String name : list) { System.out.println(name); if ("bbb".equals(name)) { list.remove(name); } } for(String name:list){ System.out.println(name); }

正常运行!打印:

复制代码
1
2
3
4
5
aaa bbb aaa ccc

原因:

 remove("bb");以后,程序认为已经遍历完成,hasNext()返回false,所以不会再执行next()去取得下一个元素"cc"。所以不会检查expectedModCount、modCount是否相等,故不会抛出异常。

上面的增强for的使用,相当于下面迭代器的使用:

复制代码
1
2
3
4
5
6
7
8
Iterator<String> iterator = list.iterator(); while (iterator.hasNext()){ String name = iterator.next(); System.out.println(name); if("bbb".equals(name)){ list.remove(name); } }

 下面看下为什么删除了倒数第二个元素后hasNext()会返回false,删除最后一个元素后hasNext却返回true!

复制代码
1
2
3
4
5
6
7
8
9
10
public E remove(Object o) { ... elementData[--size] = null; // clear to let GC do its work ... } public boolean hasNext() { //cursor是当前元素的index return cursor != size; }

 不难发现,remove(倒是第二个);的时候,--size导致cursor和size相等,所以hasNext会返回false。而remove(最后一个);会导致cursor比size大1,所以cursor!=size会返回true,即hasNext返回true。最后一个都删除了,哪里还有下一个,理所当然要抛异常了!

仅学习使用
原文作者:

看如下代码:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add("aaa"); list.add("bbb"); list.add("ccc"); for (String name : list) { System.out.println(name); if ("ccc".equals(name)) { list.remove(name); } } }

看一下抛出的异常信息:

remove()方法并不会抛出异常,抛出异常的是Itr的next方法!!但是remove()方法会导致Itr.next()发生异常。

 Itr是ArrayList的一个内部迭代器类,增强for实际上调用的就是这个迭代器的代码!看下这两个方法的代码:

复制代码
1
2
3
4
public boolean remove(Object o) { modCount++;//就是这个变量(修改次数)和异常的发生有密切关系!! ... }

再看下Itr的代码:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private class Itr implements Iterator<E> { int expectedModCount = modCount;//这里是初始化赋值 Itr() {} public E next() { checkForComodification(); ... } final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); } }

当使用增强for遍历时,会new Itr(),在初始化对象的时候expectedModCount就已经被modCount初始化确定了!!所以调用了remove()方法会使modCount++。导致expectedModCount、modCount不相等!这样再取下一个元素next()的时候,就会被检查出不相等,导致程序抛出ConcurrentModificationException异常。

补充:

1、我们直接使用ArrayList的迭代器,其实用的也是Itr类对象。所以直接用增强for会更方便!

复制代码
1
2
3
4
5
Iterator<String> iterator = list.iterator(); public Iterator<E> iterator() { return new Itr(); }

2、使用增强for遍历时,删除list中的倒数第二个元素,不会抛出ConcurrentModificationException异常。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
List<String> list = new ArrayList<>(); list.add("aaa"); list.add("bbb"); list.add("ccc"); for (String name : list) { System.out.println(name); if ("bbb".equals(name)) { list.remove(name); } } for(String name:list){ System.out.println(name); }

正常运行!打印:

复制代码
1
2
3
4
aaa bbb aaa ccc

原因:

 remove("bb");以后,程序认为已经遍历完成,hasNext()返回false,所以不会再执行next()去取得下一个元素"cc"。所以不会检查expectedModCount、modCount是否相等,故不会抛出异常。

上面的增强for的使用,相当于下面迭代器的使用:

复制代码
1
2
3
4
5
6
7
8
Iterator<String> iterator = list.iterator(); while (iterator.hasNext()){ String name = iterator.next(); System.out.println(name); if("bbb".equals(name)){ list.remove(name); } }

 下面看下为什么删除了倒数第二个元素后hasNext()会返回false,删除最后一个元素后hasNext却返回true!

复制代码
1
2
3
4
5
6
7
8
9
10
public E remove(Object o) { ... elementData[--size] = null; // clear to let GC do its work ... } public boolean hasNext() { //cursor是当前元素的index return cursor != size; }

 不难发现,remove(倒是第二个);的时候,--size导致cursor和size相等,所以hasNext会返回false。而remove(最后一个);会导致cursor比size大1,所以cursor!=size会返回true,即hasNext返回true。最后一个都删除了,哪里还有下一个,理所当然要抛异常了!

注:本文为转载博文,仅供个人学习使用


原文作者:写代码砌砖头

原文链接:https://blog.csdn.net/river66/article/details/88873872

最后

以上就是热情砖头最近收集整理的关于使用增强for遍历集合时,删除元素是如何抛出异常的?的全部内容,更多相关使用增强for遍历集合时,删除元素是如何抛出异常内容请搜索靠谱客的其他文章。

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

评论列表共有 0 条评论

立即
投稿
返回
顶部