【发布时间】:2012-05-08 10:01:06
【问题描述】:
我有一个可能包含许多元素的不可变集合(转换为Set<Integer>)。我需要一个包含该集合中的元素和一个附加元素的集合。我有一些笨拙的代码来复制集合,然后附加元素,但我正在寻找使事情尽可能高效的正确方法。
我有 Guava 可用,但我不需要使用它。
【问题讨论】:
我有一个可能包含许多元素的不可变集合(转换为Set<Integer>)。我需要一个包含该集合中的元素和一个附加元素的集合。我有一些笨拙的代码来复制集合,然后附加元素,但我正在寻找使事情尽可能高效的正确方法。
我有 Guava 可用,但我不需要使用它。
【问题讨论】:
如果 Set 是不可变的,除了复制 Set,然后添加新元素之外,我看不到任何其他方法。请记住,复制一个集合就像在创建新集合时将基本集合传递给构造函数一样简单。
【讨论】:
当我在同一个句子中阅读“不可变”和“添加到”时,我感到认知失调。您可以将新元素添加到不可变值的可变副本的末尾,但不能修改不可变集。我不知道有什么优雅的。
【讨论】:
不确定性能,但可以使用 Guava 的ImmutableSet.Builder:
import com.google.common.collect.ImmutableSet
// ...
Set<Integer> newSet = new ImmutableSet.Builder<Integer>()
.addAll(oldSet)
.add(3)
.build();
当然你也可以为自己写一个辅助方法:
public static <T> Set<T> setWith(Set<T> old, T item) {
return new ImmutableSet.Builder<T>().addAll(old).add(item).build();
}
// ...
Set<Integer> newSet = setWith(oldSet, 3);
【讨论】:
你有三个选择。
有时BitSet 是比Set<Integer> 更好的选择,具体取决于您的值的分布情况。
【讨论】:
您可以考虑 Sets.union()。构建会更快,但使用更慢。
public static <T> Set<T> setWith(Set<T> old, T item) {
return Sets.union(old, Collections.singleton(item);
}
(com.google.common.collect.Sets & java.util.Collections)
【讨论】:
使用 Java 8,您还可以使用流来实现该效果
Stream.concat(oldSet.stream(),
Stream.of(singleElement))
.collect(Collectors.toSet())
顺便说一下,从 JDK 10 开始,Collectors 还允许累积为不可变类型(与 Set.of() 等静态工厂创建的类型相同):
Stream.concat(oldSet.stream(),
Stream.of(singleElement))
.collect(Collectors.toUnmodifiableSet())
【讨论】: