看如下代码:
1
2
3
4
5
6
7
8
9
10
11
12
13public 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
4public boolean remove(Object o) { modCount++;//就是这个变量(修改次数)和异常的发生有密切关系!! ... }
再看下Itr的代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15private 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
5Iterator<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
14List<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
5aaa bbb aaa ccc
原因:
remove("bb");以后,程序认为已经遍历完成,hasNext()返回false,所以不会再执行next()去取得下一个元素"cc"。所以不会检查expectedModCount、modCount是否相等,故不会抛出异常。
上面的增强for的使用,相当于下面迭代器的使用:
1
2
3
4
5
6
7
8Iterator<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
10public 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
13public 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
4public boolean remove(Object o) { modCount++;//就是这个变量(修改次数)和异常的发生有密切关系!! ... }
再看下Itr的代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15private 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
5Iterator<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
14List<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
4aaa bbb aaa ccc
原因:
remove("bb");以后,程序认为已经遍历完成,hasNext()返回false,所以不会再执行next()去取得下一个元素"cc"。所以不会检查expectedModCount、modCount是否相等,故不会抛出异常。
上面的增强for的使用,相当于下面迭代器的使用:
1
2
3
4
5
6
7
8Iterator<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
10public 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遍历集合时,删除元素是如何抛出异常内容请搜索靠谱客的其他文章。
发表评论 取消回复