7

セットを反復処理したいのですが、セットの内容は反復中に変更されます。イテレータが作成された時点で元のセットを反復処理し、セットに追加された新しい要素を反復処理しないようにします。これはどのように可能ですか?これはsetのデフォルトの動作ですか、それともどうすればこれを実現できますか?

私が考えることができる1つの方法は、変更されない元のセットから新しいセットを取得することですが、これはエレガントではないようであり、より良い解決策があるはずです。

4

6 に答える 6

8

新しい要素が表示されないようにしたい場合は、セットのスナップショットを撮ることは私にとってまさに正しい解決策のように思えます。ConcurrentSkipListSet繰り返しを続けることができるようなセットがいくつかありますが、新しい要素を見るという点で、イテレーターの動作に関する保証はありません。

編集:CopyOnWriteArraySet必要な要件がありますが、書き込みは高価であり、適切ではないようです。

それらは私が見ることができる唯一のセットでjava.util.concurrentあり、それはそのようなコレクションの自然なパッケージです。コピーを取ることはまだ簡単である可能性が高いです:)

于 2012-06-19T18:22:08.093 に答える
7

編集:私はOPの質問をマルチスレッドによる問題を回避するのではなく、共同変更を回避するものとして解釈したため、この回答はシングルスレッドの場合のために設計されました。シングルスレッドアプローチを使用している将来の誰かに役立つことになった場合に備えて、この回答はここに残しておきます。

これを達成する直接的な方法はありません。ただし、非常に優れたオプションの1つは、2つのセットを用意することです。メインセットを繰り返し処理し、セカンダリセットに追加する必要のあるすべての新しい要素を挿入します。次に、プライマリセットを反復処理し、それが完了したら、を使用addAllしてすべての新しい要素をプライマリセットに追加します。

例えば:

Set<T> masterSet = /* ... */

Set<T> newElems = /* ... */
for (T obj: masterSet) {
     /* ... do something to each object ... */
}

masterSet.addAll(newElems);

お役に立てれば!

于 2012-06-19T18:21:56.217 に答える
2

のコピーを作成することSet 、エレガントなソリューションです。

Set<Obj> copyOfObjs = new HashSet<Obj>(originalSet);
for(Obj original : originalSet) {
    //add some more stuff to copyOfObjs
}
于 2012-06-19T18:22:42.737 に答える
0

ダミーキーでConcurrentHashMapを使用でき ます。またはConcurrentSkipListSet

于 2012-06-19T18:22:17.340 に答える
0

OPが要件を明確にしたので、ソリューションは次のようになります。

  1. 繰り返す前にセットをコピーする
  2. CopyOnWriteArraySetを使用する
  3. 独自のカスタムコードを作成し、多くの賢い人よりも賢くなるようにしてください。

#1の欠点は、必要がない場合でも(たとえば、反復中に挿入が実際に発生しない場合)、常にセットをコピーすることです。頻繁な挿入が実際のパフォーマンスを引き起こしていることが証明されない限り、オプション#2をお勧めします。問題。

于 2012-06-19T18:25:55.323 に答える
0

他の人がここで提案しているように、あなたが探しているものに対する最適な解決策はありません。それはすべて、アプリケーションのユースケース、またはセットの使用法によって異なり
ます。Setはインターフェイスであるため、Setを実装する独自のDoubleSetクラスを定義し、2つのHashSetフィールドを使用するとします。
イテレータを取得するときは、これらのセットの1つを「対話専用モード」としてマークする必要があります。これにより、addメソッドは、


Stackoverlflowを初めて使用する他のセットにのみ追加されるため、コードを埋め込む方法を理解する必要があります。私の答え:(しかし、一般的には、ジェネリックタイプTのセットを実装するMySet(ジェネリックタイプTのジェネリック)と呼ばれるクラス
が必要です。すべてのメソッドを実装する必要があり、2つのフィールドがあります。1つはiterationSetと呼ばれ、もう1つはと呼ばれます。挿入セット。
また、2つのセットに挿入するかどうかを示すブールフィールドがあります。iterator()メソッドが呼び出されるとき、このブール値はfalseに設定する必要があります。つまり、insertionSetにのみ挿入する必要があります。
イテレータを使い終わったら、2つのセットのコンテンツを同期するメソッドが必要です。
私は明確だったと思います

于 2012-06-19T18:35:39.533 に答える