复制集合的Java实现

92

有没有办法复制一个 TreeSet?也就是说,是否可以这样做?

Set <Item> itemList;
Set <Item> tempList;

tempList = itemList;

还是必须通过迭代遍历集合并逐个复制它们?


9
这句话的意思是将一个叫做itemList的列表中的所有元素添加到tempList列表中。 - dhblah
5个回答

167

另一种做法是使用复制构造函数

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,其中包含对原始Set中作为元素的对象的引用。元素对象本身不会被复制或克隆。这符合Java Collection API的设计方式:它们不会复制元素对象。


9
从Java 10开始:
Set<E> oldSet = Set.of();
Set<E> newSet = Set.copyOf(oldSet);

Set.copyOf()方法返回一个不可修改的Set,其中包含给定Collection中的元素。

给定的Collection不能为null,且不能包含任何null元素。


7

使用Java 8,您可以使用streamcollect来复制项目:

Set<Item> newSet = oldSet.stream().collect(Collectors.toSet());

或者,如果您知道集合不应更改,可以收集到ImmutableSet中:

Set<Item> newSet = oldSet.stream().collect(ImmutableSet.toImmutableSet());

9
如果你只是想复制一个集合,那么你可以使用拷贝构造函数等方式,但拷贝构造函数应该更加高效。 - Stephen C

4

Java 8+:

Set<String> copy = new HashSet<>(mySet); 

3
@Stephen C提供的复制构造函数是在您创建了一个Set(或者您知道它来自哪里)时使用的方法。如果它来自于Map.entrySet(),那么它将取决于您正在使用的Map实现: < p > findbugs

entrySet()方法允许返回基础Map的视图,在此视图中单个Entry对象在迭代期间被重用并返回。截至Java 1.6,IdentityHashMap和EnumMap都这样做。当遍历此类Map时,仅当您进入下一次迭代时,Entry值才有效。例如,如果您尝试将这样的entrySet传递给addAll方法,事情将会出错。

由于复制构造函数调用了addAll(),因此您可能会发现自己只有一个Entry的Set:最后一个。

不是所有的 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之前)的情况,但我没有任何测试。


1
这是基于观察的吗?如果是,那听起来像是addAll实现中的一个bug。就我所看到的Map实现而言,它们都会迭代entry set(在某个级别上)并提取每个条目的键和值。事实上,entry set迭代器可能每次返回相同的对象并不重要。我看到的唯一不同之处是EnumMap,其中复制构造函数本身正在克隆条目……如果源映射是一个EnumMap - Stephen C
1
@StephenC 看来你是对的:我用 IdentityHashMap 进行的测试并没有出现那个 bug。更令人不安的是,我在 Java 6u45 上进行了测试,也没有问题。我猜这是 findbugs 的一个 bug(或者是他们基于的 JDK 的规则有问题...)。我会编辑我的回答。 - Matthieu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接