TreeSet
をコピーする方法はありますか?つまり、行くことは可能ですか
Set <Item> itemList;
Set <Item> tempList;
tempList = itemList;
または、セットを物理的に反復して、1つずつコピーする必要がありますか?
これを行う別の方法は、 copy constructor を使用することです。
Collection<E> oldSet = ...
TreeSet<E> newSet = new TreeSet<E>(oldSet);
または、空のセットを作成して要素を追加します。
Collection<E> oldSet = ...
TreeSet<E> newSet = new TreeSet<E>();
newSet.addAll(oldSet);
clone
とは異なり、これらを使用すると、異なるセットクラス、異なるコンパレーターを使用したり、他の(非セット)コレクションタイプから移入することさえできます。
Set
をコピーした結果は、元のSet
の場合は要素であるオブジェクトへの参照を含む新しいSet
であることに注意してください。要素オブジェクト自体はコピーまたは複製されません。これは、Java Collection
APIが機能するように設計されている方法に準拠しています。これらのAPIは要素オブジェクトをコピーしません。
Java 8では、stream
およびcollect
を使用してアイテムをコピーできます。
Set<Item> newSet = oldSet.stream().collect(Collectors.toSet());
または、ImmutableSet
に収集できます(セットが変更されるべきでないことがわかっている場合)。
Set<Item> newSet = oldSet.stream().collect(ImmutableSet.toImmutableSet());
@Stephen Cによって指定されたコピーコンストラクターは、作成したSet
がある場合(または、どこから来たのかがわかっている場合)に移動する方法です。 Map.entrySet()
に由来する場合、使用しているMap
実装に依存します。
findbugs は言う
EntrySet()メソッドは、基礎となるMapのビューを返すことができます。このビューでは、反復中に単一のEntryオブジェクトが再利用され、返されます。 Java 1.6では、IdentityHashMapとEnumMapの両方がそうしました。そのようなマップを反復処理する場合、次の反復に進むまでエントリ値は有効です。たとえば、このようなentrySetをaddAllメソッドに渡そうとすると、事態はひどく悪くなります。
addAll()
はコピーコンストラクターによって呼び出されるので、最後の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));
編集:Java 7およびJava 6u45(Stephen Cに感謝)で実行したテストとは異なり、findbugsコメントは適切ではないようです。 Java 6の以前のバージョン(u45より前)でもそうだったかもしれませんが、テストする必要はありません。
Java 10から開始:
Set<E> oldSet = Set.of();
Set<E> newSet = Set.copyOf(oldSet);
Set.copyOf()
は、指定されたSet
の要素を含む変更不可能なCollection
を返します。
指定されたCollection
はnull
であってはならず、null
要素を含んではいけません。