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. Сами объекты элементов не копируются и не клонируются. Это соответствует способу работы CollectionAPI Java : они не копируют объекты элементов.
Вы можете ... но конструктор копирования (и т. Д.) Должен быть более эффективным, если вы просто копируете коллекцию.
Stephen C
3
Конструктор копирования, предоставленный @Stephen C, - это то, что нужно, когда у вас есть Setсозданный вами (или когда вы знаете, откуда он). Когда он исходит от a Map.entrySet(), это будет зависеть от Mapиспользуемой вами реализации:
Метод 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.
Stephen C
1
@StephenC, похоже, ты прав: тесты, которые я сделал IdentityHashMap, не приводят к этой ошибке. Больше беспокоит то, что я тестировал его на Java 6u45, и никаких проблем не было. Я предполагаю, что это ошибка в findbugs (или JDK, на котором они основали свои правила ...). Отредактирую свой ответ.
tempList.addAll(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
для копирования элементов:Или можете собрать в анкету
ImmutableSet
(если знаете, что набор не должен меняться):источник
Конструктор копирования, предоставленный @Stephen C, - это то, что нужно, когда у вас есть
Set
созданный вами (или когда вы знаете, откуда он). Когда он исходит от aMap.entrySet()
, это будет зависеть отMap
используемой вами реализации:findbugs говорит
Как
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.copyOf()
возвращает неизменяемый объект,Set
содержащий элементы данногоCollection
.Данное
Collection
не должно бытьnull
, и оно не должно содержать каких - либоnull
элементов.источник
Java 8+ :
Set<String> copy = new HashSet<>(mySet);
источник