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

时间:2015-10-06 12:44:41

标签: java linked-list iterator 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());
        }
    }
}

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

请注意,这不是about a List,而是具体关于LinkedList。如果不安全,我会问其他选择。

1 个答案:

答案 0 :(得分:5)

不,这不安全。以下代码将抛出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不会覆盖iterator()AbstractSequentialList中定义的默认实现是调用listIterator()LinkedList覆盖listIterator

引用LinkedList.listIterator的文档:

  

list-iterator是 fail-fast :如果在创建Iterator之后的任何时候对列表进行结构修改,除了通过list-iterator自己的{{ 1}}或remove方法,list-iterator将抛出add

你想要的是明确使用ListIterator而不是ConcurrentModificationException,并使用ListIterator.add

Iterator

新元素插入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()); } 返回的元素之前,因此对next()的后续调用不受影响。如果要将新项添加到迭代中,可以在添加元素后调用next()(并忽略返回值)以向后移动光标。