今天在遍历arrayList的时候,添加了一些元素进去,然后抛出ConcurrentModificationException 这个异常。然后就去网上找了下资料,抛出这个异常的原因是因为,list 集合 在遍历的时候是不允许修改list的。实质是不允许修改当前遍历list的长度的。
在 arrayList 和 linkedList 的实现里 都一个 modCount 这个遍历。 对于arrayList,在调用remove 和 clean 方法的时候,会修改 modCount 这个变量的值。在遍历的时候这个值被修改了。就会报错。 但我是对arrayList 添加元素。并不是删除,按理来说是不会修改modCount 这个值的。 可还是报错了。后来查看了源码。arrayList是用数组实现的。当你添加元素的时候,实现是会去检查数组的大小,是否需要扩容。问题就在这里,在扩容的时候,是会修改modCount 这个值的。
代码入下
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是用链表实现的。所以每一次添加其实都是在修改集合的大小。
private void linkFirst(E e) {
final Node f = first;
final Node newNode = new Node<>(null, e, f);
first = newNode;
if (f == null)
last = newNode;
else
f.prev = newNode;
size++;
modCount++;
}
那我们需要就是要修改大小怎么办呢?
对于 删除元素的话,我们可以用迭代器,然后使用迭代器的 remove 的方法。这个是对于删除来说比较通用的方法。
假如是要添加元素的的话。我没有找到很好的方法。我是用另外要给list 暂时存放需要的添加的元素。等遍历完以后,再把,需要添加的元素一起放进去。不知哪位高人有更好的方法。
本文解析了在遍历ArrayList过程中添加元素导致ConcurrentModificationException异常的原因。深入探讨了ArrayList和LinkedList内部实现机制,特别是modCount变量的作用及其如何触发异常。并提供了解决方案。
4259

被折叠的 条评论
为什么被折叠?



