即使使用iterator.remove()删除节点,HashMap也会抛出ConcurrentModification

时间:2014-11-26 07:28:38

标签: java android hashmap

操作ConcurrentModificationException时我有一个HashMap。代码如下:

    Iterator<Integer> iterator =cacheMap.keySet().iterator();
        while(iterator.hasNext()) {
        if(iterator.next() == target) {
            iterator.remove();
        }
    }

我使用的唯一操作就是删除cacheMap.put(node)。并且这些方法都在主线程中调用,包括onCreate()的{​​{1}}方法,Activity方法onPostExecute()AsyncTask方法在主线程的处理程序中。

但是,当我使用上面的方法移除节点时偶尔会在handleMessage(Message msg)中抛出ConcurrentModificationException,尽管它很少。

我已经回顾了HashMap中的相关方法。就像这样:

iterator.next()

调用@Override public Set<K> keySet() { Set<K> ks = keySet; return (ks != null) ? ks : (keySet = new KeySet()); } private final class KeyIterator extends HashIterator implements Iterator<K> { public K next() { return nextEntry().key; } } private abstract class HashIterator { int nextIndex; HashMapEntry<K, V> nextEntry = entryForNullKey; HashMapEntry<K, V> lastEntryReturned; int expectedModCount = modCount; HashIterator() { if (nextEntry == null) { HashMapEntry<K, V>[] tab = table; HashMapEntry<K, V> next = null; while (next == null && nextIndex < tab.length) { next = tab[nextIndex++]; } nextEntry = next; } } public boolean hasNext() { return nextEntry != null; } HashMapEntry<K, V> nextEntry() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); if (nextEntry == null) throw new NoSuchElementException(); HashMapEntry<K, V> entryToReturn = nextEntry; HashMapEntry<K, V>[] tab = table; HashMapEntry<K, V> next = entryToReturn.next; while (next == null && nextIndex < tab.length) { next = tab[nextIndex++]; } nextEntry = next; return lastEntryReturned = entryToReturn; } public void remove() { if (lastEntryReturned == null) throw new IllegalStateException(); if (modCount != expectedModCount) throw new ConcurrentModificationException(); HashMap.this.remove(lastEntryReturned.key); lastEntryReturned = null; expectedModCount = modCount; } } @Override public V remove(Object key) { if (key == null) { return removeNullKey(); } int hash = secondaryHash(key); HashMapEntry<K, V>[] tab = table; int index = hash & (tab.length - 1); for (HashMapEntry<K, V> e = tab[index], prev = null; e != null; prev = e, e = e.next) { if (e.hash == hash && key.equals(e.key)) { if (prev == null) { tab[index] = e.next; } else { prev.next = e.next; } modCount++; size--; postRemove(e); return e.value; } } return null; } private V removeNullKey() { HashMapEntry<K, V> e = entryForNullKey; if (e == null) { return null; } entryForNullKey = null; modCount++; size--; postRemove(e); return e.value; } /** * Subclass overrides this method to unlink entry. */ void postRemove(HashMapEntry<K, V> e) { } modCount时会检查expectedModeCountnextEntry()。但是,如果调用remove来移除节点,那么两个整数的差异似乎是不可能的。

2 个答案:

答案 0 :(得分:1)

只需使用cacheMap.remove(target)。

来自文档:

public V remove(对象键) 从此映射中删除指定键的映射(如果存在)。

请记住,HashMap只能存储给定键的一个对象,因此无需迭代所有值。

答案 1 :(得分:-3)

您不能迭代集合并从中删除项目。

使用:

Set<Integer> set = new HashSet<Integer>();
Iterator<Integer> iterator =cacheMap.keySet().iterator();
    while(iterator.hasNext()) {
        Integer key = iterator.next();
        if(key == target) {
            set.add(key );
        }
    }
    cacheMap.rmoveAll(set);
相关问题