Есть ли способ скопировать 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
них, вы можете использовать другой класс набора, другой компаратор или даже заполнить из какого-либо другого (не установленного) типа коллекции.
Обратите внимание, что результатом копирования 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 действительно только до тех пор, пока вы не перейдете к следующей итерации. Если, например, вы попытаетесь передать такой entrySet методу 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)