java.util.ConcurrentModificationException

来源:互联网 发布:macbookpro如何装软件 编辑:程序博客网 时间:2024/06/03 19:00
{        List<String> myList = new ArrayList<String>();        myList.add("1");        myList.add("2");        myList.add("3");        myList.add("4");        myList.add("5");        Iterator<String> it = myList.iterator();        while(it.hasNext()){            String value = it.next();            System.out.println("List Value:"+value);           if(value.equals("3")) myList.remove(value);//1        }        Map<String,String> myMap = new HashMap<String,String>();        myMap.put("1", "1");        myMap.put("2", "2");        myMap.put("3", "3");        Iterator<String> it1 = myMap.keySet().iterator();        while(it1.hasNext()){            String key = it1.next();            System.out.println("Map Value:"+myMap.get(key));            if(key.equals("2")){                //myMap.put("1","4");//2                myMap.put("4", "4");//3            }            System.out.println("Map Value:"+myMap.get(key));        }    }System.out.println("----------------");        it1 = myMap.keySet().iterator();        while (it1.hasNext()){            String key = it1.next();            System.out.println("Map Value:"+myMap.get(key));        }

1和3出执行都会发生并发修改异常,是由next()方法抛出的,而2处不会。单独执行2处的结果:
Map Value:1
Map Value:1
Map Value:2
Map Value:2
Map Value:3
Map Value:3


Map Value:4
Map Value:2
Map Value:3

可以发现,Map中的value被覆盖了。但在第一次的遍历中,获取的还是原值,只有重新再获取迭代器,才能获取到被覆盖后的值。

Since we are updating the existing key value in the myMap, its size has not been changed and we are not getting ConcurrentModificationException. Note that the output may differ in your system because HashMap keyset is not ordered like list. If you will uncomment the statement where I am adding a new key-value in the HashMap, it will cause ConcurrentModificationException.

why?
查看源代码:JDK1.8
HashMap:
关键代码

public class HashMap<K,V> extends AbstractMap<K,V>    implements Map<K,V>, Cloneable, Serializable {    private static final long serialVersionUID = 362498820763181265L;    transient int modCount;     public V put(K key, V value) {        return putVal(hash(key), key, value, false, true);    }    final V putVal(int hash, K key, V value, boolean onlyIfAbsent,                   boolean evict) {        Node<K,V>[] tab; Node<K,V> p; int n, i;        if ((tab = table) == null || (n = tab.length) == 0)            n = (tab = resize()).length;        if ((p = tab[i = (n - 1) & hash]) == null)            tab[i] = newNode(hash, key, value, null);        else {            Node<K,V> e; K k;            if (p.hash == hash &&                ((k = p.key) == key || (key != null && key.equals(k))))                e = p;            else if (p instanceof TreeNode)                e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);            else {                for (int binCount = 0; ; ++binCount) {                    if ((e = p.next) == null) {                        p.next = newNode(hash, key, value, null);                        if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st                            treeifyBin(tab, hash);                        break;                    }                    if (e.hash == hash &&                        ((k = e.key) == key || (key != null && key.equals(k))))                        break;                    p = e;                }            }            if (e != null) { // existing mapping for key                V oldValue = e.value;                if (!onlyIfAbsent || oldValue == null)                    e.value = value;                afterNodeAccess(e);                return oldValue;            }        }        ++modCount;//1        if (++size > threshold)            resize();        afterNodeInsertion(evict);        return null;    }final class KeySet extends AbstractSet<K> {        public final int size()                 { return size; }        public final void clear()               { HashMap.this.clear(); }        public final Iterator<K> iterator()     { return new KeyIterator(); }//2        public final boolean contains(Object o) { return containsKey(o); }        public final boolean remove(Object key) {            return removeNode(hash(key), key, null, false, true) != null;        }        public final Spliterator<K> spliterator() {            return new KeySpliterator<>(HashMap.this, 0, -1, 0, 0);        }        public final void forEach(Consumer<? super K> action) {            Node<K,V>[] tab;            if (action == null)                throw new NullPointerException();            if (size > 0 && (tab = table) != null) {                int mc = modCount;                for (int i = 0; i < tab.length; ++i) {                    for (Node<K,V> e = tab[i]; e != null; e = e.next)                        action.accept(e.key);                }                if (modCount != mc)                    throw new ConcurrentModificationException();            }        }    }        final class KeyIterator extends HashIterator        implements Iterator<K> {        public final K next() { return nextNode().key; }    }        final Node<K,V> nextNode() {            Node<K,V>[] t;            Node<K,V> e = next;            if (modCount != expectedModCount)//3                throw new ConcurrentModificationException();            if (e == null)                throw new NoSuchElementException();            if ((next = (current = e).next) == null && (t = table) != null) {                do {} while (index < t.length && (next = t[index++]) == null);            }            return e;        } abstract class HashIterator {        Node<K,V> next;        // next entry to return        Node<K,V> current;     // current entry        int expectedModCount;  // for fast-fail        int index;             // current slot        HashIterator() {            expectedModCount = modCount;//4            Node<K,V>[] t = table;            current = next = null;            index = 0;            if (t != null && size > 0) { // advance to first entry                do {} while (index < t.length && (next = t[index++]) == null);            }        }}

1->2->3->4
参考:http://www.journaldev.com/378/java-util-concurrentmodificationexception

阅读全文
1 0
原创粉丝点击