關於 java.util.ConcurrentModificationException 的認識

今天在遍歷arrayList的時候,添加了一些元素進去,而後拋出ConcurrentModificationException 這個異常。而後就去網上找了下資料,拋出這個異常的緣由是由於,list 集合 在遍歷的時候是不容許修改list的。實質是不容許修改當前遍歷list的長度的。java

在 arrayList 和 linkedList 的實現裏 都一個 modCount 這個遍歷。 對於arrayList,在調用remove 和 clean 方法的時候,會修改 modCount 這個變量的值。在遍歷的時候這個值被修改了。就會報錯。 但我是對arrayList 添加元素。並非刪除,按理來講是不會修改modCount 這個值的。 可仍是報錯了。後來查看了源碼。arrayList是用數組實現的。當你添加元素的時候,實現是會去檢查數組的大小,是否須要擴容。問題就在這裏,在擴容的時候,是會修改modCount 這個值的。數組

代碼入下code

public boolean add(E e) {
    ensureCapacityInternal(size + 1);  // Increments modCount!!  次方法用來檢查是否要擴大數組的大小
    elementData[size++] = e;
    return true;
}
    
private void ensureCapacityInternal(int minCapacity) {
    if (elementData == EMPTY_ELEMENTDATA) {
        // 加入 數組仍是爲空話,選擇默認的大小
        minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
    }
    //擴大數組的大小
    ensureExplicitCapacity(minCapacity);
}

private void ensureExplicitCapacity(int minCapacity) {
        modCount++; 

        // overflow-conscious code  傳入進來的容量必須大於當前的容量
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }

對於linkedList 的話 你調用add 方法的時候就直接修改modCount 的值了。 由於linkedList是用鏈表實現的。因此每一次添加其實都是在修改集合的大小。ci

private void linkFirst(E e) {
        final Node<E> f = first;
        final Node<E> newNode = new Node<>(null, e, f);
        first = newNode;
        if (f == null)
            last = newNode;
        else
            f.prev = newNode;
        size++;
        modCount++;
    }

那咱們須要就是要修改大小怎麼辦呢?
對於 刪除元素的話,咱們能夠用迭代器,而後使用迭代器的 remove 的方法。這個是對於刪除來講比較通用的方法。element

假如是要添加元素的的話。我沒有找到很好的方法。我是用另外要給list 暫時存放須要的添加的元素。等遍歷完之後,再把,須要添加的元素一塊兒放進去。不知哪位高人有更好的方法。rem

相關文章
相關標籤/搜索