Czy istnieje sposób na skopiowanie TreeSet
? To znaczy, czy można iść
Set <Item> itemList;
Set <Item> tempList;
tempList = itemList;
czy też musisz fizycznie iterować zestawy i kopiować je jeden po drugim?
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 nowy Set
zawierają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 Collection
interfejsów API języka Java : nie kopiują one obiektów elementów.
W Javie 8 możesz używać stream
i collect
kopiować elementy:
Set<Item> newSet = oldSet.stream().collect(Collectors.toSet());
Lub możesz zebrać do ImmutableSet
(jeśli wiesz, że zestaw nie powinien się zmieniać):
Set<Item> newSet = oldSet.stream().collect(ImmutableSet.toImmutableSet());
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 a Map.entrySet()
, będzie to zależeć od używanej Map
implementacji:
Findbugs mówi
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.
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ć nowe Entry
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.
addAll
implementacji. FWIW, wszystkie Map
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, to EnumMap
sytuacja, w której sam konstruktor kopiujący klonował wpisy ... jeśli mapa źródłowa była EnumMap
.
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<E> oldSet = Set.of();
Set<E> newSet = Set.copyOf(oldSet);
Set.copyOf()
zwraca niemodyfikowalny Set
zawierający elementy danego Collection
.
Podane Collection
nie może być null
i nie może zawierać żadnych null
elementów.
tempList.addAll(itemList)