Collection<E> oldSet = ...
TreeSet<E> newSet = new TreeSet<E>(oldSet);
Lub stwórz pusty zestaw i dodaj elementy:
Collection<E> oldSet = ...
TreeSet<E> newSet = new TreeSet<E>();
newSet.addAll(oldSet);
W przeciwieństwie do clonenich pozwalają na użycie innej klasy zestawu, innego komparatora, a nawet wypełnienie z innego (niezestawionego) typu kolekcji.
Zauważ, że wynikiem kopiowania a Setjest nowy Setzawierający odniesienia do obiektów, które są elementami oryginału Set. Same obiekty elementów nie są kopiowane ani klonowane. Jest to zgodne ze sposobem działania Collectioninterfejsów API języka Java : nie kopiują one obiektów elementów.
Możesz ... ale konstruktor kopiujący (itp.) Powinien być bardziej wydajny, jeśli po prostu kopiujesz kolekcję.
Stephen C,
3
Konstruktor kopiujący podany przez @Stephen C jest drogą do zrobienia, gdy Setmasz utworzony przez siebie (lub gdy wiesz, skąd pochodzi). Jeśli pochodzi z a Map.entrySet(), będzie to zależeć od używanej Mapimplementacji:
Metoda entrySet () może zwrócić widok bazowej mapy, w której pojedynczy obiekt Entry jest ponownie używany i zwracany podczas iteracji. Począwszy od Javy 1.6, zrobiły to zarówno IdentityHashMap, jak i EnumMap. Podczas iteracji przez taką mapę wartość Entry jest ważna tylko do momentu przejścia do następnej iteracji. Jeśli na przykład spróbujesz przekazać taki entrySet do metody addAll, wszystko pójdzie źle.
Jak addAll()nazywa konstruktor kopiujący, możesz znaleźć zestaw zawierający tylko jeden wpis: ostatni.
MapJednak nie wszystkie implementacje to robią, więc jeśli wiesz, że Twoja implementacja jest bezpieczna pod tym względem, zdecydowanie najlepszym rozwiązaniem jest konstruktor kopiujący. W przeciwnym razie sam musiałbyś tworzyć nowe Entryobiekty:
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));
Edycja: W przeciwieństwie do testów, które przeprowadziłem na Javie 7 i Javie 6u45 (dzięki Stephenowi C), komentarz findbugs nie wydaje się już odpowiedni. Mogło tak być we wcześniejszych wersjach Java 6 (przed U45), ale nie mam żadnej do testowania.
Czy jest to oparte na obserwacji? Jeśli tak, to brzmi jak błąd w addAllimplementacji. FWIW, wszystkie Mapimplementacje , których szukałem, iterują zestaw wpisów (na pewnym poziomie) i wyodrębniają klucz i wartość dla każdego z nich . Fakt, że iterator zestawu pozycji może zwracać ten sam obiekt za każdym razem, nie ma znaczenia. Jedyny przypadek, w którym zauważyłem, że był inny, to EnumMapsytuacja, w której sam konstruktor kopiujący klonował wpisy ... jeśli mapa źródłowa była EnumMap.
Stephen C
1
@StephenC wygląda na to, że masz rację: testy, które wykonałem IdentityHashMap, nie prowadzą do tego błędu. Bardziej niepokojące jest to, że przetestowałem go na Javie 6u45 i też nie było problemu. Wydaje mi się, że jest to błąd w findbugs (lub JDK, na którym oparli swoje zasady ...). Zmienię odpowiedź.
tempList.addAll(itemList)
Odpowiedzi:
Innym sposobem na to jest użycie konstruktora kopiującego :
Collection<E> oldSet = ... TreeSet<E> newSet = new TreeSet<E>(oldSet);
Lub stwórz pusty zestaw i dodaj elementy:
Collection<E> oldSet = ... TreeSet<E> newSet = new TreeSet<E>(); newSet.addAll(oldSet);
W przeciwieństwie do
clone
nich pozwalają na użycie innej klasy zestawu, innego komparatora, a nawet wypełnienie z innego (niezestawionego) typu kolekcji.Zauważ, że wynikiem kopiowania a
Set
jest nowySet
zawierający odniesienia do obiektów, które są elementami oryginałuSet
. Same obiekty elementów nie są kopiowane ani klonowane. Jest to zgodne ze sposobem działaniaCollection
interfejsów API języka Java : nie kopiują one obiektów elementów.źródło
W Javie 8 możesz używać
stream
icollect
kopiować elementy:Lub możesz zebrać do
ImmutableSet
(jeśli wiesz, że zestaw nie powinien się zmieniać):źródło
Konstruktor kopiujący podany przez @Stephen C jest drogą do zrobienia, gdy
Set
masz utworzony przez siebie (lub gdy wiesz, skąd pochodzi). Jeśli pochodzi z aMap.entrySet()
, będzie to zależeć od używanejMap
implementacji:Findbugs mówi
Jak
addAll()
nazywa konstruktor kopiujący, możesz znaleźć zestaw zawierający tylko jeden wpis: ostatni.Map
Jednak nie wszystkie implementacje to robią, więc jeśli wiesz, że Twoja implementacja jest bezpieczna pod tym względem, zdecydowanie najlepszym rozwiązaniem jest konstruktor kopiujący. W przeciwnym razie sam musiałbyś tworzyć noweEntry
obiekty: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));
Edycja: W przeciwieństwie do testów, które przeprowadziłem na Javie 7 i Javie 6u45 (dzięki Stephenowi C), komentarz findbugs nie wydaje się już odpowiedni. Mogło tak być we wcześniejszych wersjach Java 6 (przed U45), ale nie mam żadnej do testowania.
źródło
addAll
implementacji. FWIW, wszystkieMap
implementacje , których szukałem, iterują zestaw wpisów (na pewnym poziomie) i wyodrębniają klucz i wartość dla każdego z nich . Fakt, że iterator zestawu pozycji może zwracać ten sam obiekt za każdym razem, nie ma znaczenia. Jedyny przypadek, w którym zauważyłem, że był inny, toEnumMap
sytuacja, w której sam konstruktor kopiujący klonował wpisy ... jeśli mapa źródłowa byłaEnumMap
.IdentityHashMap
, nie prowadzą do tego błędu. Bardziej niepokojące jest to, że przetestowałem go na Javie 6u45 i też nie było problemu. Wydaje mi się, że jest to błąd w findbugs (lub JDK, na którym oparli swoje zasady ...). Zmienię odpowiedź.Począwszy od Java 10 :
Set.copyOf()
zwraca niemodyfikowalnySet
zawierający elementy danegoCollection
.Podane
Collection
nie może byćnull
i nie może zawierać żadnychnull
elementów.źródło
Java 8+ :
Set<String> copy = new HashSet<>(mySet);
źródło