How to initialize HashSet values by construction?
我需要用初始值创建一个
1 2 3 | Set<String> h = new HashSet<String>(); h.add("a"); h.add("b"); |
有没有一种方法可以在一行代码中做到这一点?例如,它对最终的静态字段很有用。
我使用的速记法不是很省时,但只适用于一行:
1 |
同样,这是不省时的,因为您正在构造一个数组,转换为一个列表,并使用该列表创建一个集合。
在初始化静态最终集时,我通常这样写:
1 2 |
稍微不那么难看,效率对于静态初始化来说并不重要。
集合文字是为Java 7调度的,但没有实现。所以还没有自动的。
您可以使用Guava的
1 | Sets.newHashSet("a","b","c") |
或者,您可以使用以下语法,这将创建一个匿名类,但这是黑客行为:
1 2 3 4 | Set<String> h = new HashSet<String>() {{ add("a"); add("b"); }}; |
在Java 8中,我将使用:
1 | Set<String> set = Stream.of("a","b").collect(Collectors.toSet()); |
这将给您一个可变的
1 2 |
使用爪哇10(不可更改组件)
1 2 | Set<String> strSet1 = Stream.of("A","B","C","D") .collect(Collectors.toUnmodifiableSet()); |
在这里,收集器将实际返回不可更改的组件在爪哇9号作为声明
使用爪哇9(不可更改组件)ZZU1
We have 12 overloaded versions of this convenience factory method:
static Set of()
static Set of(E e1)
static Set of(E e1, E e2) // ....and so on
static Set of(E... elems)
那么,一个自然的问题是,为什么我们需要过多的版本,当我们变了。答案是:每一个Var-Arg方法创建一个内部阵列,并且有过多的负载版本,可以避免不必要的对象创建,并且也可以将我们从收藏在头顶上。
使用Java 8(可修改组件)
使用爪哇流域
1 2 3 4 5 6 7 8 9 10 | Set<String> strSet1 = Stream.of("A","B","C","D") .collect(Collectors.toCollection(HashSet::new)); // stream from an array (String[] stringArray) Set<String> strSet2 = Arrays.stream(stringArray) .collect(Collectors.toCollection(HashSet::new)); // stream from a list (List<String> stringList) Set<String> strSet3 = stringList.stream() .collect(Collectors.toCollection(HashSet::new)); |
Using Java 8(Unmodible sets)
Using collections.unmodifiableset-we can use
1 |
但它看起来很慢,我们可以写我们自己的收藏家
1 2 3 4 5 6 7 8 | class ImmutableCollector { public static <T> Collector<T, Set<T>, Set<T>> toImmutableSet() { return Collector.of(HashSet::new, Set::add, (l, r) -> { l.addAll(r); return l; }, Collections::unmodifiablSet); } } |
然后用作:
1 2 | Set<String> strSet4 = Stream.of("A","B","C","D") .collect(ImmutableCollector.toImmutableSet()); |
Using collectors.collectingandthen-another approach is to use the method
1 2 3 | import static java.util.stream.Collectors.*; Set<String> strSet5 = Stream.of("A","B","C","D").collect(collectingAndThen( toCollection(HashSet::new),Collections::unmodifiableSet)); |
如果我们只关心
注意的一点是,方法
有几种方法:
双括号初始化
这是一种创建匿名内部类的技术,该类具有实例初始值设定项,在创建实例时将
1 2 3 4 | Set<String> s = new HashSet<String>() {{ add("a"); add("b"); }} |
记住,这实际上会在每次使用时创建一个新的
一种实用方法
编写一个返回用所需元素初始化的
1 2 3 4 5 6 7 8 |
上面的代码只允许使用
使用图书馆
许多库都有一个方便的方法来初始化集合对象。
例如,google collections有一个
如果集合中只有一个初始值,这就足够了:
1 |
你可以在Java 6中完成:
1 |
但是为什么呢?我不认为它比显式添加元素更具可读性。
2.One of the most convenient ways is using of generic collections.addall()method,which takes a collection and varargs:
1 2 |
我觉得最易读的就是简单地使用谷歌的番石榴:
1 | Set<String> StringSet = Sets.newSet("a","b","c"); |
With Java 9 you can do the following:
1 |
你会得到一个不可磨灭的组件For details see the Oracle documentation of interface set.
coobird's answer's utility函数在创建新
1 2 3 4 5 6 7 | public static <T> Set<T> newHashSet(T... objs) { Set<T> set = new HashSet<T>(); for (T o : objs) { set.add(o); } return set; } |
如果集合的包含类型是枚举,则有Java构建的工厂方法(自1.5以来):
1 | Set<MY_ENUM> MY_SET = EnumSet.of( MY_ENUM.value1, MY_ENUM.value2, ... ); |
对于Eclipse集合,有几种不同的方法来初始化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | Set<String> set = Sets.mutable.with("a","b"); HashSet<String> hashSet = Sets.mutable.with("a","b").asLazy().into(new HashSet<String>()); Set<String> synchronizedSet = Sets.mutable.with("a","b").asSynchronized(); Set<String> unmodifiableSet = Sets.mutable.with("a","b").asUnmodifiable(); MutableSet<String> mutableSet = Sets.mutable.with("a","b"); MutableSet<String> synchronizedMutableSet = Sets.mutable.with("a","b").asSynchronized(); MutableSet<String> unmodifiableMutableSet = Sets.mutable.with("a","b").asUnmodifiable(); ImmutableSet<String> immutableSet = Sets.immutable.with("a","b"); ImmutableSet<String> immutableSet2 = Sets.mutable.with("a","b").toImmutable(); CharSet charSet = CharSets.mutable.with('a', 'b'); CharSet synchronizedCharSet = CharSets.mutable.with('a', 'b').asSynchronized(); CharSet unmodifiableCharSet = CharSets.mutable.with('a', 'b').asUnmodifiable(); MutableCharSet mutableCharSet = CharSets.mutable.with('a', 'b'); ImmutableCharSet immutableCharSet = CharSets.immutable.with('a', 'b'); ImmutableCharSet immutableCharSet2 = CharSets.mutable.with('a', 'b').toImmutable(); |
Eclipse集合与Java 5 - 8兼容。
注意:我是Eclipse集合的提交者。
1 2 | import com.google.common.collect.Sets; Sets.newHashSet("a","b"); |
黄金
1 2 | import com.google.common.collect.ImmutableSet; ImmutableSet.of("a","b"); |
有点复杂,但从Java 5工作:
使用助手方法使其可读:
1 2 3 4 5 |
(Ugly)Double Brace initiatization without side effects:
1 2 3 4 | Set<String> a = new HashSet<>(new HashSet<String>() {{ add("1"); add("2"); }}) |
但在某些情况下,如果我们说谎是一种很好的烟雾,使最终的收藏无法变形,那么它可能是真正的使用:
1 2 3 4 |
使用爪哇8我们可以创造
1 |
如果我们想要一个不可更改的设置,我们可以创造一个有效的方法,例如:
1 2 3 4 5 6 7 8 | public static <T, A extends Set<T>> Collector<T, A, Set<T>> toImmutableSet(Supplier<A> supplier) { return Collector.of( supplier, Set::add, (left, right) -> { left.addAll(right); return left; }, Collections::unmodifiableSet); } |
This method can be used as:
1 |
只是一个小提示,不管您最终使用的是哪种好方法,如果这是一个通常未经修改的默认值(就像您正在创建的库中的默认设置),那么最好遵循此模式:
1 2 3 4 | // Initialize default values with the method you prefer, even in a static block // It's a good idea to make sure these defaults aren't modifiable private final static Set<String> DEFAULT_VALUES = Collections.unmodifiableSet(...); private Set<String> values = DEFAULT_VALUES; |
其好处取决于您为该类创建的实例的数量以及更改默认值的可能性。
如果您决定遵循这个模式,那么您还可以选择最可读的set初始化方法。由于不同方法之间效率的细微差别可能无关紧要,因为您将只初始化一次集合。
With the release of Java9 and the convenience factory methods this is possible in a cleaner way:
Can use static block for initiatization:
1 2 3 4 5 6 7 8 9 10 11 12 |
这是一个优雅的解决方案:
1 2 3 4 5 6 7 8 9 | public static final <T> Set<T> makeSet(@SuppressWarnings("unchecked") T... o) { return new HashSet<T>() { private static final long serialVersionUID = -3634958843858172518L; { for (T x : o) add(x); } }; } |
建筑物模式可能在这里使用。今天我也有同样的问题。在我需要做突变手术的地方,我可以把它交给超级阶级制造商,所以他们也可以继续把同样的一个设置,转动一个新的弦结构,摆脱那一组的孩子。建筑物阶级我写的样子(以我为例,它是一个静态的内在阶级,但它可以是它自己的独立阶级和它自己):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | public interface Builder<T> { T build(); } static class StringSetBuilder implements Builder<Set<String>> { private final Set<String> set = new HashSet<>(); StringSetBuilder add(String pStr) { set.add(pStr); return this; } StringSetBuilder addAll(Set<String> pSet) { set.addAll(pSet); return this; } @Override public Set<String> build() { return set; } } |
《经济、社会、文化权利国际公约》第1条和《经济、社会、文化权利国际公约》第1条的通知最后,方法说明了建筑物封装的一个参照点。Below includerates then how to use this set builder:
1 2 3 4 5 6 7 8 9 10 11 | class SomeChildClass extends ParentClass { public SomeChildClass(String pStr) { super(new StringSetBuilder().add(pStr).build()); } } class ParentClass { public ParentClass(Set<String> pSet) { super(new StringSetBuilder().addAll(pSet).add("my own str").build()); } } |