简体   繁体   English

Java集合,允许在迭代时添加和删除

[英]Java collection to allow adding and removing while iterating

I am interested if there is any framework that implements a collection that would have the following behavior. 我对是否有实现收集具有以下行为的集合的框架感兴趣。


Suppose it initially contains: [1, 2, 3] 假设它最初包含:[1、2、3]

  • I iterate it (using an iterator) and reach element 2, now I add 4 to the end (the collection will now be [1, 2, 3, 4]). 我对其进行迭代(使用迭代器)并到达元素2,现在我在末尾添加4(集合现在为[1、2、3、4])。
  • now I create a new iterator and iterate the collection, resulting in [1, 2, 3, 4] 现在,我创建一个新的迭代器并对集合进行迭代,得到[1、2、3、4]
  • I continue iterating with the first iterator and it will give me just 3 and return 我继续使用第一个迭代器进行迭代,它将只给我3个并返回
  • now resetting the first iterator will give me [1, 2, 3, 4] (similar to creating a new one). 现在重置第一个迭代器将得到[1、2、3、4](类似于创建一个新的迭代器)。

Same should apply for removal of elements. 同样也应适用于删除元素。 If I remove 3 instead of adding, the second iterator should give me [1, 2] while the first one will still give me 3 and the end. 如果我删除3而不是添加,第二个迭代器应该给我[1,2],而第一个迭代器仍然给我3,最后一个。


So when I get and iterator I want it to give me the collection I had when I created the iterator (even if I iterate it later, on I iterate a bit and continue later), when I reset the iterator, it gets garbage collected it will update to the latest versions and I should be able to have multiple iterator instances created at different times that will give different versions depending on the contents of the array when the iterator was created. 因此,当我获取并使用迭代器时,我希望它给我创建迭代器时所拥有的集合(即使稍后进行迭代,在我进行一点迭代后再继续),当我重置迭代器时,它会被垃圾回收将更新为最新版本,我应该能够在不同的时间创建多个迭代器实例,这些实例将根据创建迭代器时数组的内容提供不同的版本。

I would need it to work well with multiple threads and preferable have an efficient implementation. 我需要它与多个线程一起很好地工作,并且最好有一个高效的实现。

Does anyone know of any implementation of such a collection, or do I have to implement it myself? 有人知道这样的集合有任何实现吗,还是我必须自己实现?

java.util.concurrent.CopyOnWriteArrayList行为将与此类似,只是没有Java集合具有“重置”迭代器的功能-但是获得新的迭代器而不是重置具有您在此处要求的效果。

What you describe looks very similar to how CopyOnWriteArrayList works: 您所描述的内容与CopyOnWriteArrayList工作原理非常相似:

  • once you start iterating, you can change the collection (including from another thread) without affecting the iteration 一旦开始迭代,就可以更改集合(包括来自另一个线程的集合)而不会影响迭代
  • if you create a new iterator it will be based on the collection at the creation time 如果您创建一个新的迭代器,它将基于创建时的集合
  • it is thread safe 这是线程安全的

Simple example below with the following output: 以下是带有以下输出的简单示例:

Iterator 1 - 1 迭代器1-1
4 has been added 已添加4
Iterator 2 - 1 迭代器2-1
Iterator 2 - 2 迭代器2-2
Iterator 2 - 3 迭代器2-3
Iterator 2 - 4 迭代器2-4
Iterator 1 - 2 迭代器1-2
Iterator 1 - 3 迭代器1-3

public static void main(String[] args) throws InterruptedException {
    final List<Integer> list = new CopyOnWriteArrayList<Integer>();
    list.addAll(Arrays.asList(1, 2, 3));
    new Thread(new Runnable() {

        @Override
        public void run() {
            for (Integer i : list) {
                System.out.println("Iterator 1 - " + i);
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {}
            }
        }
    }).start();
    Thread.sleep(10);
    list.add(4);
    System.out.println("4 has been added");
    for (Integer i : list) {
        System.out.println("Iterator 2 - " + i);
    }

}

You can use the ImmutableCollections from the guava library. 您可以使用来自guava库的ImmutableCollections

The returned ImmutableList is frequently -- not always, but frequently -- a constant-overhead view, rather than an explicit copy. 返回的ImmutableList通常(并非总是但经常)是恒定开销的视图,而不是显式副本。 That said, it's often smarter than your average List -- for example, it'll use the efficient contains methods of the backing collection. 就是说,它通常比平均列表更聪明-例如,它将使用后备集合的有效包含方法。

You could make use of java.util.concurrent.CopyOnWriteArrayList<E> 您可以利用java.util.concurrent.CopyOnWriteArrayList<E>

According documentation: 根据文档:

A thread-safe variant of ArrayList in which all mutative operations (add, set, and so on) are implemented by making a fresh copy of the underlying array. ArrayList的线程安全变体,其中所有可变操作(添加,设置等)都通过对基础数组进行全新复制来实现。

Its costly, but thread safe. 它昂贵,但线程安全。

This is ordinarily too costly, but may be more efficient than alternatives when traversal operations vastly outnumber mutations, and is useful when you cannot or don't want to synchronize traversals, yet need to preclude interference among concurrent threads. 通常这样做的成本太高,但是在遍历操作的数量远远超过变异的情况下,它可能比替代方法更有效,并且在您无法或不想同步遍历而又需要防止并发线程之间的干扰时很有用。 The "snapshot" style iterator method uses a reference to the state of the array at the point that the iterator was created. “快照”样式的迭代器方法在创建迭代器时使用对数组状态的引用。

As the iteration occurs over a kind of snapshot, the operations ( remove , set , and add ) on Iterator itself are not supported. 由于迭代发生在某种快照上,因此不支持Iterator本身的操作( removesetadd )。

javolution有线程安全的FastMap

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM