在迭代时将项目添加到链表是否安全

Is it safe to add items to a linked list while iterating

在迭代时向 LinkedList 添加项目是否安全?

class Worker {

    final LinkedList<Foo> worklist = new LinkedList<>();

    public void work() {

        Iterator<Foo> iterator = worklist.iterator();

        while (iterator.hasNext()) {

            Foo foo = iterator.next();

            doSomethingWith(foo);
        }
    }

    public void doSomethingWith(Foo foo) {

        // do something with foo            

        // and possibly add one (or more) foo's to the worklist
        if (expression) {
            worklist.add(new Foo());
        }
    }
}

如果不是,如何以安全有效的方式实施此行为?

请注意,这不是 about a List,而是关于 LinkedList。如果它不安全,我会询问替代方案。

不,这不安全。以下代码将抛出 ConcurrentModificationException:

final LinkedList<Foo> worklist = new LinkedList<>();
worklist.add(new Foo());
Iterator<Foo> iterator = worklist.iterator();
while (iterator.hasNext()) {
    Foo foo = iterator.next();
    worklist.add(new Foo());
}

LinkedList does not override iterator() and the default implementation, defined in AbstractSequentialList is to call listIterator(), and LinkedList does override listIterator.

引用 LinkedList.listIterator 的文档:

The list-iterator is fail-fast: if the list is structurally modified at any time after the Iterator is created, in any way except through the list-iterator's own remove or add methods, the list-iterator will throw a ConcurrentModificationException.

你想要的是明确使用 ListIterator, instead of an Iterator, and use ListIterator.add:

final LinkedList<Foo> worklist = new LinkedList<>();
worklist.add(new Foo());
ListIterator<Foo> iterator = worklist.listIterator();
while (iterator.hasNext()) {
    Foo foo = iterator.next();
    iterator.add(new Foo());
}

新元素插入到 return 由 next() 编辑的元素之前,因此对 next() 的后续调用不受影响。如果要将新项添加到迭代中,可以在添加元素后调用 previous()(并忽略 return 值)以向后移动光标。