【问题标题】:How to modify subList without ConcurrentModificationException?如何在没有 ConcurrentModificationException 的情况下修改 subList?
【发布时间】:2013-06-01 23:59:16
【问题描述】:

ListIterator 有点问题。

我已经开始迭代原始列表[1, 4, 5],我在14之间。然后我将列表修改为[1, 2, 3, 4, 5]。现在我想迭代原始列表的其余部分。这里我给出一个示例代码:

public class Test {
    public static void main(String[] args) {        
        List<Integer> list = new LinkedList<Integer>();  // []
        list.add(new Integer(1));  // [1]
        list.add(new Integer(4));  // [1, 4]
        list.add(new Integer(5));  // [1, 4, 5]
        ListIterator<Integer> iterator = (ListIterator<Integer>) list.iterator();

        System.out.println(iterator.next()); // prints [1]

        // modify subList
        List<Integer> subList = list.subList(0, 2);    // [1, 4]
        subList.add(1, new Integer(2));    // [1, 2, 4]
        subList.add(2, new Integer(3));    // [1, 2, 3, 4]

        // need to print rest of oryginal list: [4, 5]
        while (iterator.hasNext())
            System.out.println(iterator.next());
    }
}

当我执行它时,我得到了 java.util.ConcurrentModificationException。你知道我怎样才能正确地做到这一点吗?

【问题讨论】:

  • 在迭代时不能修改某些内容。您必须制作一个副本才能修改和迭代原件。

标签: java iterator linked-list sublist


【解决方案1】:

你误解了list.subList的用法。

子列表只是原始列表一部分的视图。如果您修改子列表,您实际上是在修改原始列表。

你想要的是复制原始列表的一部分:

List<Integer> subList = new ArrayList<Integer>(list.subList(0,2));

【讨论】:

    【解决方案2】:

    如果您通过迭代器(而不是通过列表)对列表进行修改,那么您将不会得到 ConcurrentModificationException

        System.out.println(iterator.next()); // prints [1]
    
        iterator.add(new Integer(2)); // [1, 2, 4]
        iterator.add(new Integer(3)); // [1, 2, 3, 4]
    
        while (iterator.hasNext())
            System.out.println(iterator.next());
    

    【讨论】:

    • 2 和 3 将被自动跳过。来自关于 ListIterator#add 的文档:“新元素插入到隐式光标之前:对 next 的后续调用将不受影响,对 previous 的后续调用将返回新元素。”
    • 修改子列表时,无法访问原来的迭代器。
    • @WojciechKo 在这种情况下,另一种选择是使用CopyOnWriteArrayList - 它在快照上返回迭代器,因此它们永远不会抛出ConcurrentModificationExceptions。另一种选择是使用ConcurrentLinkedQueue - 它的迭代器是弱一致的,并且永远不会抛出ConcurrentModificationExceptions
    • @WojciechKo 或者你可以使用ConcurrentDoublyLinkedList,它的迭代器也是弱一致的
    猜你喜欢
    • 2011-01-04
    • 2011-10-20
    • 2015-03-29
    • 2023-04-03
    • 1970-01-01
    • 2015-07-30
    • 2021-04-21
    • 1970-01-01
    • 2021-04-14
    相关资源
    最近更新 更多