关于for each循环不能直接使用集合的remove方法的原因
来源:互联网 发布:anywhere远程桌面软件 编辑:程序博客网 时间:2024/05/17 07:06
记录一下为何在使用for each 循环时,不能在循环体内直接使用集合的remove方法的原因;
因为for each循环的底层原理时用iterator来实现的,所以在遍历元素的时实际操作使用的时iterator;
但我们在循环体内部使用集合自身的remove方法时,以ArrayList源码为例:
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 }
可以看见源码里面有个modCount++,该属性时ArrayList自身属性 默认为0,代表修改的次数,每次删除modCount都会自增;
因为for each底层原理时iterator,所以我们再看下iterator中hasnext、next方法源码:
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]; }
其中关注下checkForComodification()方法 ,其源码:
final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); }
其中有个expectedModCount 该参数时iterator中的属性 ,代表使用iterator修改集合元素的次数;
当集合属性modCount 于expectedModCount次数不相等,则会抛异常;
当我们再for each中直接使用集合的remove方法时 modCount增加了,但是iterator并没有增加导致抛异常;
如果我们使用iterator再for each循环体中使用remove 不会抛异常的原因可以通过iterator中remove源码可知:
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.this.remove(lastRet) 调用的就是集合本身的remove方法 :
public E remove(int index) { rangeCheck(index); modCount++; E oldValue = elementData(index); 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 return oldValue; }
可以看见modCount会自增,所以在调用iterator的remove方法时modCount等于expectedModCount;
综上,则是再for each循环体不能直接使用集合的remove方法但能用iterator的remove方法的原因。
阅读全文
0 0
- 关于for each循环不能直接使用集合的remove方法的原因
- 关于java for()循环 remove 的使用
- 关于java for()循环 remove 的使用
- Java中For-Each循环的使用
- easyUI accordion 使用和remove方法 for循环的异常
- for循环和jquery的each()跳出循环的方法
- iterable和for-each循环集合的注意事项
- Java学习之for-each循环与集合的遍历
- 关于for循环与for-each的效率比较
- for each循环的作用
- 关于for-each与删除集合节点的思考
- 关于集合List的remove方法
- 注意在使用ArrayList进行for循环遍历的时候不能直接移除下标
- 简单介绍下for each循环的使用
- for each和for循环的对比
- 增强的for循环(for each)
- Java循环中remove方法的使用
- 关于js中each()使用return不能终止循环
- linux下svn服务器搭建及创建分支
- 读
- 从零基础到大数据专家要掌握的知识
- 数据类型
- Java多线程编程-(3)-线程本地ThreadLocal的介绍与使用
- 关于for each循环不能直接使用集合的remove方法的原因
- SQL基础语句
- 码云上使用git
- 还原eclipse默认界面风格
- JavaScript-表单验证
- ubuntu安装Nginx
- 请你谈谈Cookie的弊端
- Java:Object
- SQL 和 NoSQL