Чи є спосіб скопіювати 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. Самі об'єкти елементів не копіюються і не клонуються. Це відповідає тому, як CollectionAPI 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)