Java中的ArrayList是一个实现了List接口的动态数组,可以自动扩容。ArrayList提供了很多方便的方法,可以让我们对数组进行快速的操作。但是,在多线程环境下,操作ArrayList时容易抛出ConcurrentModificationException异常。下面是一个完整攻略,来详细讲解如何解析ArrayList和ConcurrentModificationException。
1. ArrayList源码解析
1.1 ArrayList实现原理
ArrayList内部是用一个Object类型的数组elementData来存储数据的。当我们向ArrayList中添加元素时,如果elementData中的空间不足,就会新建一个大一些的数组,并将原来的元素复制到新的数组中。
private void grow(int minCapacity) {
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity);
}
1.2 ArrayList常用方法解析
- add(E e): 添加元素到ArrayList中。
- get(int index): 根据下标获取ArrayList中的元素。
- remove(int index): 根据下标删除ArrayList中的元素。
- size(): 返回ArrayList中元素的个数。
2. ConcurrentModificationException解析
当我们在使用Iterator遍历ArrayList时,如果在遍历的过程中改变了ArrayList的结构(如添加或删除元素),就会抛出ConcurrentModificationException异常。
ArrayList<String> list = new ArrayList<>();
list.add("A");
list.add("B");
for (String str : list) {
if (str.equals("B")) {
list.remove(str);
}
}
在上面的代码中,我们在遍历的过程中尝试删除一个元素,这时就会抛出ConcurrentModificationException异常。
3. 解决ConcurrentModificationException异常
为了避免ConcurrentModificationException异常的出现,我们可以使用以下方法:
3.1 使用Iterator来遍历ArrayList
在使用Iterator遍历ArrayList的过程中,如果在遍历时改变了ArrayList的结构,就会抛出ConcurrentModificationException异常。因此,我们可以在遍历时通过Iterator对象的remove方法来删除元素。
ArrayList<String> list = new ArrayList<>();
list.add("A");
list.add("B");
Iterator<String> iter = list.iterator();
while (iter.hasNext()) {
String str = iter.next();
if (str.equals("B")) {
iter.remove();
}
}
3.2 使用CopyOnWriteArrayList
CopyOnWriteArrayList是一个并发安全的ArrayList实现。它的实现原理是:在对CopyOnWriteArrayList进行修改时,会先复制一份原有的ArrayList,然后对复制出来的ArrayList进行修改,修改完成后再将原有的ArrayList引用指向新的ArrayList,以此来保证并发安全。
CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
list.add("A");
list.add("B");
for (String str : list) {
if (str.equals("B")) {
list.remove(str);
}
}
在上面的代码中,我们在遍历的过程中尝试删除一个元素,这时不会抛出ConcurrentModificationException异常,因为CopyOnWriteArrayList是并发安全的。
4. 示例说明
示例1:遍历时删除元素
以下示例演示了在使用Iterator遍历ArrayList时,尝试删除一个元素,导致抛出ConcurrentModificationException异常。
ArrayList<String> list = new ArrayList<>();
list.add("A");
list.add("B");
for (String str : list) {
if (str.equals("B")) {
list.remove(str);
}
}
示例2:使用CopyOnWriteArrayList
以下示例演示了如何使用CopyOnWriteArrayList来解决并发问题。
CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
list.add("A");
list.add("B");
for (String str : list) {
if (str.equals("B")) {
list.remove(str);
}
}
在这个示例中,我们在遍历的过程中尝试删除一个元素,但不会抛出ConcurrentModificationException异常,因为CopyOnWriteArrayList是并发安全的。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java源码解析ArrayList及ConcurrentModificationException - Python技术站