有没有办法复制TreeSet
?也就是说,有可能去
Set <Item> itemList;
Set <Item> tempList;
tempList = itemList;
还是您需要物理遍历这些集合并一一复制?
Answers:
另一种方法是使用复制构造函数:
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
。元素对象本身不会被复制或克隆。这符合Java Collection
API设计的工作方式:它们不复制元素对象。
使用Java 8,您可以使用stream
和collect
复制项目:
Set<Item> newSet = oldSet.stream().collect(Collectors.toSet());
或者,您可以收集到一个ImmutableSet
(如果您知道该集合不应更改):
Set<Item> newSet = oldSet.stream().collect(ImmutableSet.toImmutableSet());
@Stephen C给出的副本构造函数是Set
创建后(或知道它来自何处)的处理方式。如果来自Map.entrySet()
,则取决于Map
您使用的实现:
允许entrySet()方法返回基础Map的视图,该基础Map中的单个Entry对象在迭代过程中被重用并返回。从Java 1.6开始,IdentityHashMap和EnumMap都这样做了。遍历此类Map时,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上进行的测试不同(感谢Stephen C),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)