セットJavaのコピー


83

をコピーする方法はありTreeSetますか?つまり、行くことは可能ですか

Set <Item> itemList;
Set <Item> tempList;

tempList = itemList;

または、セットを物理的に繰り返して、1つずつコピーする必要がありますか?


7
tempList.addAll(itemList)
dhblah 2011

回答:


155

これを行う別の方法は、コピーコンストラクターを使用することです。

Collection<E> oldSet = ...
TreeSet<E> newSet = new TreeSet<E>(oldSet);

または、空のセットを作成して要素を追加します。

Collection<E> oldSet = ...
TreeSet<E> newSet = new TreeSet<E>();
newSet.addAll(oldSet);

cloneこれらとは異なり、異なるセットクラス、異なるコンパレータを使用したり、他の(セットされていない)コレクションタイプからデータを入力したりすることができます。


aをコピーした結果は、元のの場合は要素であるオブジェクトへの参照を含むSet新しいものであることに注意してください。要素オブジェクト自体はコピーまたは複製されません。これは、Java APIが機能するように設計されている方法に準拠しています。つまり、要素オブジェクトをコピーしません。SetSetCollection


7

Java 8では、アイテムを使用streamおよびcollectコピーできます。

Set<Item> newSet = oldSet.stream().collect(Collectors.toSet());

または、ImmutableSet(セットを変更してはならないことがわかっている場合)に収集することもできます。

Set<Item> newSet = oldSet.stream().collect(ImmutableSet.toImmutableSet());

8
できます...しかし、単にコレクションをコピーする場合は、コピーコンストラクター(など)の方が効率的です。
スティーブン

3

@Stephen Cによって提供されるコピーコンストラクターは、Set作成したものがある場合(または、それがどこから来ているかがわかっている場合)に使用する方法です。から来る場合は、使用Map.entrySet()しているMap実装によって異なります。

findbugsは言う

entrySet()メソッドは、単一のEntryオブジェクトが再利用され、反復中に返される、基になるMapのビューを返すことができます。Java 1.6以降、IdentityHashMapとEnumMapの両方がそうしました。このようなマップを反復処理する場合、エントリ値は次の反復に進むまでのみ有効です。たとえば、そのようなentrySetをaddAllメソッドに渡そうとすると、事態はひどく悪くなります。

addAll()最後の1:コピーコンストラクタによって呼び出され、1つだけのエントリの設定を自分で見つけるかもしれません。

Mapただし、すべての実装がそれを行うわけではないため、実装がその点で安全であることがわかっている場合は、コピーコンストラクターが間違いなく進むべき道です。それ以外の場合は、Entry自分で新しいオブジェクトを作成する必要があります。

Set<K,V> copy = new HashSet<K,V>(map.size());
for (Entry<K,V> e : map.entrySet())
    copy.add(new java.util.AbstractMap.SimpleEntry<K,V>(e));

編集:Java7とJava6u45で実行したテスト(Stephen Cのおかげで)とは異なり、findbugsのコメントはもはや適切ではないようです。以前のバージョンのJava6(u45より前)ではそうであったかもしれませんが、テストする必要はありません。


1
これは観察に基づいていますか?もしそうなら、それはaddAll実装のバグのように聞こえます。FWIW、Map私が調べた実装はすべて、エントリセットを(あるレベルで)繰り返し、それぞれのキーと値を抽出します。エントリセットのイテレータが同じオブジェクトを返す可能性があるという事実は、毎回重要ではありません。私が見た唯一の違いはEnumMap、コピーコンストラクター自体がエントリのクローンを作成していた場合です...ソースマップがEnumMap
スティーブンC

1
@StephenCあなたが正しいようです:私が行ったテストはIdentityHashMapそのバグにつながりません。さらに厄介なのは、Java 6u45でテストしたところ、問題がなかったことです。これはfindbugs(または彼らがルールに基づいたJDK ...)のバグだと思います。答えを編集します。
マシュー

3

始まってJavaの10

Set<E> oldSet = Set.of();
Set<E> newSet = Set.copyOf(oldSet);

Set.copyOf()Set指定されたの要素を含む変更不可能なものを返しますCollection

与えられたものはであるCollection必要がありnullnull要素を含むことはできません。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.