📌  相关文章
📜  Java中的 CopyOnWriteArrayList iterator() 方法(1)

📅  最后修改于: 2023-12-03 15:01:52.391000             🧑  作者: Mango

Java中的 CopyOnWriteArrayList iterator() 方法

CopyOnWriteArrayList 是 Java 中的一个线程安全的 List 实现,它的 iterator() 方法返回一个迭代器,用于遍历集合中的元素。

CopyOnWriteArrayList 简介

CopyOnWriteArrayList 是一个线程安全的 ArrayList 实现,它的核心原理是在修改 ArrayList 时,先将原有的数据复制一份出来,对副本进行修改,完成后再将副本赋值给原有数组。这样做的好处是读取操作可以并发进行,而不需要加锁,从而提高了读取的效率。

但是,这种实现方式的缺陷也很明显,每次修改操作都需要复制整个数组,占用大量的内存和 CPU 资源。因此,在修改操作较多的应用场景下,CopyOnWriteArrayList 的性能可能会受到较大的影响。

iterator() 方法简介

CopyOnWriteArrayList 的 iterator() 方法返回一个迭代器,用于遍历集合中的元素。与普通的 ArrayList 不同,CopyOnWriteArrayList 的迭代器对集合的修改是不可见的,即如果在迭代的过程中进行了添加、删除等操作,迭代器依然会访问到修改前的集合元素。这种行为被称为“弱一致性”。

CopyOnWriteArrayList 的 iterator() 方法的语法如下:


public Iterator<E> iterator() {
    return new COWIterator<E>(getArray(), 0);
}

其中,getArray() 方法返回当前集合的快照,即复制的副本。

iterator() 方法的实现原理

CopyOnWriteArrayList 的 iterator() 方法实际上就是返回一个内部类 COWIterator 的实例。COWIterator 实现了 Iterator 接口,用于遍历集合中的元素。

以下是 COWIterator 类的简化实现代码:


final class COWIterator<E> implements Iterator<E> {
    
    private Object[] snapshot;  // 集合快照,即副本
    
    private int cursor;  // 游标
    
    public COWIterator(Object[] elements, int initialCursor) {
        this.snapshot = elements;
        this.cursor = initialCursor;
    }
    
    public boolean hasNext() {
        return cursor < snapshot.length;
    }
    
    public E next() {
        return (E) snapshot[cursor++];
    }
    
    public void remove() {
        throw new UnsupportedOperationException();
    }
}

注意,COWIterator 实例内部维护了一个游标,它用于记录当前遍历到集合中的哪个位置。在 hasNext() 方法中,COWIterator 会检查游标是否已经到达集合的末尾,如果是,则返回 false,否则返回 true。

在 next() 方法中,COWIterator 会先返回当前游标指向的元素,然后将游标移动到下一个位置。

而在 remove() 方法中,由于 CopyOnWriteArrayList 是线程安全的,因此迭代器的 remove() 方法是不支持操作的,在调用时会抛出 UnsupportedOperationException 异常。

总结

CopyOnWriteArrayList 是一个线程安全的 List 实现,在遍历集合元素时,可以使用 iterator() 方法获取一个迭代器。与普通的 ArrayList 不同,CopyOnWriteArrayList 的迭代器对集合的修改是不可见的,即如果在迭代的过程中进行了添加、删除等操作,迭代器依然会访问到修改前的集合元素。这种行为被称为“弱一致性”。需要注意的是,由于 CopyOnWriteArrayList 是线程安全的,因此迭代器的 remove() 方法是不支持操作的,在调用时会抛出 UnsupportedOperationException 异常。