java 将单个元素添加到不可变集合的有效且优雅的方法是什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10354286/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is an efficient and elegant way to add a single element to an immutable set?
提问by Max
I have an immutable set (cast as a Set<Integer>
) that potentially contains many elements. I need a Collection that contains the elements from that set plus one additional element. I have kludgy code in place to copy the set, then append the element, but I'm looking for The Right Way that keeps things as efficient as possible.
我有一个不可变的集合(转换为 a Set<Integer>
),它可能包含许多元素。我需要一个包含该集合中的元素以及一个附加元素的集合。我有笨拙的代码来复制集合,然后附加元素,但我正在寻找使事情尽可能高效的正确方法。
I have Guava available, though I do not require its use.
我有番石榴可用,但我不需要它的使用。
回答by Niklas B.
Not sure about performance, but you can use Guava's ImmutableSet.Builder
:
不确定性能,但您可以使用 Guava 的ImmutableSet.Builder
:
import com.google.common.collect.ImmutableSet
// ...
Set<Integer> newSet = new ImmutableSet.Builder<Integer>()
.addAll(oldSet)
.add(3)
.build();
Of course you can also write yourself a helper method for that:
当然,您也可以为此编写一个辅助方法:
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);
回答by Darren Gilroy
You might consider Sets.union(). Construction would be faster, but use slower.
您可能会考虑 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)
(com.google.common.collect.Sets & java.util.Collections)
回答by Peter Lawrey
You have three options.
你有三个选择。
- Use a mutable set.
- Check the element isn't already present, if not create a copy of the set and add an element.
- Create a wrapper set which includes the previous set and the element.
- 使用可变集。
- 检查元素是否已经存在,如果不存在,则创建该集合的副本并添加一个元素。
- 创建一个包含前一个集合和元素的包装集。
Sometimes a BitSet
is a better choice than Set<Integer>
depending on the distribution of your values.
有时 aBitSet
是比Set<Integer>
取决于您的值的分布更好的选择。
回答by hvgotcodes
If the Set is immutable, I don't see any way to do it other than copy the Set, and then add your new element. Remember, copying a set is as easy as passing the base set to the constructor function when creating the new set.
如果 Set 是不可变的,除了复制 Set,然后添加新元素之外,我看不到任何其他方法。请记住,复制一个集合就像在创建新集合时将基集合传递给构造函数一样简单。
回答by Brice
Using Java 8 you can also use streams for that effect
使用 Java 8,您还可以使用流来实现该效果
Stream.concat(oldSet.stream(),
Stream.of(singleElement))
.collect(toSet())
回答by Mike Samuel
When you want better performance than a full copy, and you have an ordering over elements, you can use an effectively immutable wrapper around a B+ treeto get good incremental set performance.
当您想要比完整副本更好的性能,并且您对元素进行排序时,您可以在B+ 树周围使用有效的不可变包装器来获得良好的增量集性能。
Adding an item to a B+ tree requires O(log(n)) time and incremental allocation, not O(n) as you get with ImmutableSet.builder().addAll(...).add(...).build()
. This means that building a set from n incremental adds is O(n*log(n)), not O(sqr(n)).
将项目添加到 B+ 树需要 O(log(n)) 时间和增量分配,而不是 O(n) ImmutableSet.builder().addAll(...).add(...).build()
。这意味着从 n 个增量添加构建一个集合是 O(n*log(n)),而不是 O(sqr(n))。
This answerhas a pointer to a jdbm library so it might be worth looking at jdbm:jdbm
.
回答by duffymo
I'm experiencing cognitive dissonance when I read "immutable" and "add to" in the same sentence. You can add a new element to the end of a mutable copy of the immutable values, but you can't modify the immutable set. I don't know of anything elegant.
当我在同一个句子中读到“immutable”和“add to”时,我正在经历认知失调。您可以在不可变值的可变副本的末尾添加新元素,但不能修改不可变集。我不知道有什么优雅的。