Чи є спосіб скопіювати TreeSet
? Тобто, чи можна їхати
Set <Item> itemList;
Set <Item> tempList;
tempList = itemList;
чи вам доводиться фізично переглядати набори та копіювати їх по одному?
Відповіді:
Інший спосіб зробити це - використовувати конструктор копіювання :
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
є нове, Set
що містить посилання на об'єкти, які є елементами, якщо оригінал Set
. Самі об'єкти елементів не копіюються і не клонуються. Це відповідає тому, як Collection
API Java розроблені для роботи: вони не копіюють об'єкти елементів.
За допомогою Java 8 ви можете використовувати stream
і collect
копіювати елементи:
Set<Item> newSet = oldSet.stream().collect(Collectors.toSet());
Або ви можете отримати до ImmutableSet
(якщо ви знаєте, що набір не повинен змінюватися):
Set<Item> newSet = oldSet.stream().collect(ImmutableSet.toImmutableSet());
Конструктор копіювання, наданий @Stephen C, - це той шлях, який Set
ви створили (або коли знаєте, звідки він береться). Коли воно походить від a Map.entrySet()
, це буде залежати від Map
реалізації, яку ви використовуєте:
findbugs каже
Методу entrySet () дозволено повертати подання базової карти, в якій один об'єкт Entry використовується повторно і повертається під час ітерації. Починаючи з Java 1.6, це робили і IdentityHashMap, і EnumMap. Під час ітерації через таку карту значення Entry є дійсним лише до переходу до наступної ітерації. Наприклад, якщо ви спробуєте передати такий запис SetSet до методу addAll, все піде не так.
Як addAll()
називається конструктор копіювання, ви можете опинитися з набором лише одного запису: останнього.
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 (завдяки Степану С), коментар findbugs вже не здається доречним. Це могло бути у попередніх версіях Java 6 (до u45), але у мене немає жодної для тестування.
addAll
реалізації. FWIW, Map
реалізації, які я переглядав, всі повторюють набір записів (на якомусь рівні) і витягують ключ і значення для кожного з них . Той факт, що ітератор набору записів може повертати той самий об'єкт кожного разу, не має значення. Єдиний випадок, який я бачив, був інший, EnumMap
коли конструктор копіювання клонував записи ... якщо вихідна карта була EnumMap
.
IdentityHashMap
займався, не призводять до цієї помилки. Більше турбує те, що я тестував його на Java 6u45 і теж не було проблем. Я думаю, це помилка у findbugs (або JDK, на якому вони базували свої правила ...). Я відредагую свою відповідь.
Починаючи з Java 10 :
Set<E> oldSet = Set.of();
Set<E> newSet = Set.copyOf(oldSet);
Set.copyOf()
повертає немодифікований, Set
що містить елементи заданого Collection
.
Дане Collection
не повинно бути null
, і воно не повинно містити жодних null
елементів.
tempList.addAll(itemList)