在这里为什么可以使用迭代器来删除集合中的元素而不能够使从集合中直接删除呢? removevoid remove()从迭代器指向的 collection 中移除迭代器返回的最后一个元素(可选操作)。每次调用 next 只能调用一次此方法。如果进行迭代时用调用此方法之外的其他方式修改了该迭代器所指向的 collection,则迭代器的行为是不确定的。 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 用remove删除元素之后,该Collection不就发生改变了吗,那么该迭代器不就失效了吗 用remove删除元素之后,该Collection不就发生改变了吗,那么该迭代器不就失效了吗是的,一般iterator中remove会经常出错,但也不是一定就出错,尽量不要这么使用。 这个,我也想知道,瞅瞅源码吧单步调试,进入到这里:private abstract class HashIterator<E> implements Iterator<E> { Entry<K,V> next; // next entry to return int expectedModCount; // For fast-fail int index; // current slot Entry<K,V> current; // current entry HashIterator() { expectedModCount = modCount; if (size > 0) { // advance to first entry Entry[] t = table; while (index < t.length && (next = t[index++]) == null) ; } } public final boolean hasNext() { return next != null; } final Entry<K,V> nextEntry() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); Entry<K,V> e = next; if (e == null) throw new NoSuchElementException(); if ((next = e.next) == null) { Entry[] t = table; while (index < t.length && (next = t[index++]) == null) ; } current = e; return e; }//调用的这个方法 public void remove() { if (current == null) throw new IllegalStateException();//玄机就在这里:expectedModCount,拷贝网上找来的说明,/** *在Iterator的内部有个expectedModCount 变量, *该变量每次初始化*Iterator的时候等于ArrayList的modCount,modCount记录了对ArrayList的结构修改次数, *在通过Iterator对ArrayList进行结构的修改的时候都会将expectedModCount 与modCount同步, *但是如果在通过Iterator访问的时候同时又通过索引的方式去修改ArrayList的结构的话, *由于通过索引的方式只会修改modCount不会同步修改expectedModCount 就会导致 *modCount和expectedModCount 不相等就会抛ConcurrentModificationException, *这也就是Iterator的fail-fast,快速失效的。所以只要采取一种方式操作ArrayList就不会出问题, *当然ArrayList不是线程安全的,此处不讨论对线程问题。 * http://sushe1424.iteye.com/blog/1110796*/ if (modCount != expectedModCount) throw new ConcurrentModificationException(); Object k = current.key; current = null; HashMap.this.removeEntryForKey(k); expectedModCount = modCount; } } /** * Removes and returns the entry associated with the specified key * in the HashMap. Returns null if the HashMap contains no mapping * for this key. */ final Entry<K,V> removeEntryForKey(Object key) { int hash = (key == null) ? 0 : hash(key.hashCode()); int i = indexFor(hash, table.length); Entry<K,V> prev = table[i]; Entry<K,V> e = prev; while (e != null) { Entry<K,V> next = e.next; Object k; if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) { modCount++; size--; if (prev == e) table[i] = next; else prev.next = next; e.recordRemoval(this); return e; } prev = e; e = next; } return e; }看看和直接删除有什么不一样:直接删除先调用hashset里的,没有对expectedModCount做同步,这就会出错了! public boolean remove(Object o) { return map.remove(o)==PRESENT; }map.remove(o)其实也是hashMap里的removeEntryForKey() public V remove(Object key) { Entry<K,V> e = removeEntryForKey(key); return (e == null ? null : e.value); } 用java模拟oracle的to_date()函数 一道面试题,关于英文、汉字字符编码及字节方面的疑问? list 里面都是一样格式的map怎么 初学者求解一道JAVA编程题! 一个jdbc 的问题!急 JAVA如何解析word编辑完成的.doc文档 初学者,一个问题卡住了,请教大家,谢谢 怎么获得一个数的整数部分,和小数部分? 子类方法中引用了父类中非同名方法,但该父类引用了该子类同名父类方法(有点绕,第一次发帖) 怎样显示JTextArea滚动条? 关于JDK最新版本的安装及环境设置问题,求指教! RMI传输对象时,对象的方法如何处理?
Entry<K,V> next; // next entry to return
int expectedModCount; // For fast-fail
int index; // current slot
Entry<K,V> current; // current entry HashIterator() {
expectedModCount = modCount;
if (size > 0) { // advance to first entry
Entry[] t = table;
while (index < t.length && (next = t[index++]) == null)
;
}
} public final boolean hasNext() {
return next != null;
} final Entry<K,V> nextEntry() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
Entry<K,V> e = next;
if (e == null)
throw new NoSuchElementException(); if ((next = e.next) == null) {
Entry[] t = table;
while (index < t.length && (next = t[index++]) == null)
;
}
current = e;
return e;
}
//调用的这个方法
public void remove() { if (current == null)
throw new IllegalStateException();
//玄机就在这里:expectedModCount,拷贝网上找来的说明,
/**
*在Iterator的内部有个expectedModCount 变量,
*该变量每次初始化*Iterator的时候等于ArrayList的modCount,modCount记录了对ArrayList的结构修改次数,
*在通过Iterator对ArrayList进行结构的修改的时候都会将expectedModCount 与modCount同步,
*但是如果在通过Iterator访问的时候同时又通过索引的方式去修改ArrayList的结构的话,
*由于通过索引的方式只会修改modCount不会同步修改expectedModCount 就会导致
*modCount和expectedModCount 不相等就会抛ConcurrentModificationException,
*这也就是Iterator的fail-fast,快速失效的。所以只要采取一种方式操作ArrayList就不会出问题,
*当然ArrayList不是线程安全的,此处不讨论对线程问题。 * http://sushe1424.iteye.com/blog/1110796
*/
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
Object k = current.key;
current = null;
HashMap.this.removeEntryForKey(k);
expectedModCount = modCount;
} }
/**
* Removes and returns the entry associated with the specified key
* in the HashMap. Returns null if the HashMap contains no mapping
* for this key.
*/
final Entry<K,V> removeEntryForKey(Object key) {
int hash = (key == null) ? 0 : hash(key.hashCode());
int i = indexFor(hash, table.length);
Entry<K,V> prev = table[i];
Entry<K,V> e = prev; while (e != null) {
Entry<K,V> next = e.next;
Object k;
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k)))) {
modCount++;
size--;
if (prev == e)
table[i] = next;
else
prev.next = next;
e.recordRemoval(this);
return e;
}
prev = e;
e = next;
} return e;
}看看和直接删除有什么不一样:
直接删除先调用hashset里的,没有对expectedModCount做同步,这就会出错了!
public boolean remove(Object o) {
return map.remove(o)==PRESENT;
}
map.remove(o)其实也是hashMap里的removeEntryForKey()
public V remove(Object key) {
Entry<K,V> e = removeEntryForKey(key);
return (e == null ? null : e.value);
}