5

如果有任何框架实现具有以下行为的集合,我很感兴趣。


假设它最初包含: [1, 2, 3]

  • 我迭代它(使用迭代器)并到达元素 2,现在我将 4 添加到末尾(集合现在将是 [1, 2, 3, 4])。
  • 现在我创建一个新的迭代器并迭代集合,得到 [1, 2, 3, 4]
  • 我继续使用第一个迭代器进行迭代,它只会给我 3 并返回
  • 现在重置第一个迭代器会给我 [1, 2, 3, 4] (类似于创建一个新的)。

同样应该适用于删除元素。如果我删除 3 而不是添加,第二个迭代器应该给我 [1, 2] 而第一个迭代器仍然会给我 3 和结尾。


所以当我得到和迭代器时,我希望它给我创建迭代器时拥有的集合(即使我稍后迭代它,我会迭代一点并稍后继续),当我重置迭代器时,它会被垃圾收集将更新到最新版本,我应该能够在不同时间创建多个迭代器实例,这些实例将根据创建迭代器时数组的内容提供不同的版本。

我需要它与多个线程一起工作,并且最好有一个有效的实现。

有谁知道这样一个集合的任何实现,还是我必须自己实现它?

4

5 回答 5

7

java.util.concurrent.CopyOnWriteArrayList将表现得像这样,除了没有 Java 集合具有迭代器的“重置”——但是获取一个新的迭代器而不是重置具有您在此处请求的效果。

于 2012-06-27T13:59:38.370 回答
6

您描述的内容与CopyOnWriteArrayList工作方式非常相似:

  • 一旦开始迭代,就可以更改集合(包括来自另一个线程)而不影响迭代
  • 如果您创建一个新的迭代器,它将基于创建时的集合
  • 它是线程安全的

下面的简单示例具有以下输出:

迭代器 1 - 1
4 已添加
迭代器 2 - 1
迭代器 2 - 2
迭代器 2 - 3
迭代器 2 - 4
迭代器 1 - 2
迭代器 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);
    }

}
于 2012-06-27T13:59:49.550 回答
3

您可以使用 guava 库中的ImmutableCollections

返回的 ImmutableList 经常——不总是,但经常——一个常量开销视图,而不是显式副本。也就是说,它通常比普通的 List 更聪明——例如,它将使用支持集合的有效 contains 方法。

于 2012-06-27T14:05:22.843 回答
3

你可以利用java.util.concurrent.CopyOnWriteArrayList<E>

根据文件:

ArrayList 的线程安全变体,其中所有可变操作(添加、设置等)都是通过制作底层数组的新副本来实现的。

它的成本很高,但线程安全。

这通常成本太高,但是当遍历操作的数量大大超过突变时,它可能比替代方法更有效,并且在您不能或不想同步遍历但需要排除并发线程之间的干扰时很有用。“快照”风格的迭代器方法使用对创建迭代器时数组状态的引用。

由于迭代发生在一种快照上,因此不支持对其自身的操作( removesetadd) 。Iterator

于 2012-06-27T14:06:10.283 回答
0

javolution 有线程安全的 FastMap

于 2012-06-27T14:08:04.430 回答