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

Tim*_*Tim 5 java iterator linked-list listiterator

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());
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

请注意,这不是关于aList,而是关于a LinkedList.如果它不安全,我会问有关替代方案.

Tun*_*aki 6

不,这不安全.以下代码将抛出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());
}
Run Code Online (Sandbox Code Playgroud)

LinkedList不覆盖iterator(),默认实现,定义AbstractSequentialList是调用listIterator(),并LinkedList覆盖listIterator.

引用以下文档LinkedList.listIterator:

list-iterator是快速失败的:如果在创建Iterator之后的任何时候对列表进行结构修改,除了通过list-iterator自己的removeadd方法之外,list-iterator将抛出一个ConcurrentModificationException.

你想要的是使用explicitely a ListIterator而不是a Iterator,并使用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());
}
Run Code Online (Sandbox Code Playgroud)

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