5

次のような動作をするコレクションを実装するフレームワークがあるかどうかに興味があります。


最初に次のものが含まれているとします:[1、2、3]

  • 私はそれを(イテレーターを使用して)繰り返し、要素2に到達します。ここで、最後に4を追加します(コレクションは[1、2、3、4]になります)。
  • ここで、新しいイテレータを作成してコレクションを反復すると、[1、2、3、4]になります。
  • 私は最初のイテレータで反復を続けます、そしてそれは私にちょうど3を与えて戻ってきます
  • ここで、最初のイテレータをリセットすると、[1、2、3、4]が得られます(新しいイテレータを作成するのと同様です)。

同じことが要素の除去にも当てはまります。追加する代わりに3を削除すると、2番目のイテレータは[1、2]を返しますが、最初のイテレータは3と最後を返します。


したがって、イテレータを取得して、イテレータを作成したときに持っていたコレクションを取得したいのですが(後でイテレータを繰り返しても、少し繰り返して後で続行します)、イテレータをリセットすると、ガベージコレクションが行われます。は最新バージョンに更新され、イテレータが作成されたときの配列の内容に応じて異なるバージョンを提供する複数のイテレータインスタンスを異なる時間に作成できるはずです。

複数のスレッドでうまく機能するためにそれが必要であり、効率的な実装が望ましいです。

誰かがそのようなコレクションの実装を知っていますか、それとも私はそれを自分で実装する必要がありますか?

4

5 に答える 5

7

java.util.concurrent.CopyOnWriteArrayListJavaコレクションにイテレータの「リセット」がないことを除いて、このように動作しますが、リセットする代わりに新しいイテレータを取得すると、ここで要求した効果があります。

于 2012-06-27T13:59:38.370 に答える
6

あなたが説明することは、どのように機能するかと非常によく似ていますCopyOnWriteArrayList

  • 反復を開始すると、反復に影響を与えることなく、コレクションを(別のスレッドからのものを含めて)変更できます。
  • 新しいイテレータを作成すると、作成時のコレクションに基づきます
  • スレッドセーフです

以下の簡単な例と次の出力:

イテレータ1〜14
が追加されました
イテレータ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は、明示的なコピーではなく、頻繁に(常にではありませんが、頻繁に)定数オーバーヘッドビューです。とはいえ、多くの場合、平均的なリストよりも賢いです。たとえば、バッキングコレクションの効率的なcontainsメソッドを使用します。

于 2012-06-27T14:05:22.843 に答える
3

あなたは利用することができますjava.util.concurrent.CopyOnWriteArrayList<E>

ドキュメントによると:

基になる配列の新しいコピーを作成することによってすべての変異操作(追加、設定など)が実装されるArrayListのスレッドセーフなバリアント。

コストはかかりますが、スレッドセーフです。

これは通常コストがかかりすぎますが、トラバーサル操作がミューテーションの数を大幅に上回っている場合は他の方法よりも効率的であり、トラバーサルを同期できない、または同期したくないが、並行スレッド間の干渉を排除する必要がある場合に役立ちます。「スナップショット」スタイルのイテレータメソッドは、イテレータが作成された時点での配列の状態への参照を使用します。

反復は一種のスナップショットで発生するため、それ自体に対する操作(、、、removeおよびsetaddIteratorサポートされていません。

于 2012-06-27T14:06:10.283 に答える
0

javolutionにはスレッドセーフなFastMapがあります

于 2012-06-27T14:08:04.430 に答える