如何通过构造来初始化HashSet值?

我需要用初始值创build一个Set

 Set<String> h = new HashSet<String>(); h.add("a"); h.add("b"); 

有没有办法在一行代码中做到这一点?

有一个速记,我用它不是非常省时,但适合在一个单一的线上:

 Set<String> h = new HashSet<>(Arrays.asList("a", "b")); 

同样,这是不是时间效率,因为你正在构build一个数组,转换为一个列表,并使用该列表来创build一个集合。

初始化静态最终集时,我通常会这样写:

 public static final String[] SET_VALUES = new String[] { "a", "b" }; public static final Set<String> MY_SET = new HashSet<>(Arrays.asList(SET_VALUES)); 

稍微不那么丑陋,效率对静态初始化无关紧要。

集合文字预定为Java 7,但没有进入。所以没有自动呢。

你可以使用番石榴的Sets

 Sets.newHashSet("a", "b", "c") 

或者你可以使用下面的语法,这将创build一个匿名类,但它是hacky:

 Set<String> h = new HashSet<String>() {{ add("a"); add("b"); }}; 

在Java 8中,我将使用:

 Set<String> set = Stream.of("a", "b").collect(Collectors.toSet()); 

这给你一个可变的Set用“a”和“b”预先初始化。 请注意,在JDK 8中,这确实会返回一个HashSet ,但规范并不能保证它,这在将来可能会改变。 如果你特别想要一个HashSet ,可以这样做:

 Set<String> set = Stream.of("a", "b") .collect(Collectors.toCollection(HashSet::new)); 

有几种方法:

双大括号初始化

这是一种创build匿名内部类的方法,它有一个实例初始化程序,在创build实例时将String添加到自身:

 Set<String> s = new HashSet<String>() {{ add("a"); add("b"); }} 

请记住,每次使用HashSet时,实际上都会创build一个新的子类,即使不需要显式地写一个新的子类。

一种实用方法

编写一个返回一个用所需元素初始化的Set的方法并不难写:

 public static Set<String> newHashSet(String... strings) { HashSet<String> set = new HashSet<String>(); for (String s : strings) { set.add(s); } return set; } 

上面的代码只允许使用String ,但是允许使用generics的任何types都不是太困难。

使用图书馆

许多库有一个方便的方法来初始化集合对象。

例如, Google Collections具有Sets.newHashSet(T...)方法,该方法将使用特定types的元素填充HashSet

你可以在Java 6中做到这一点:

 Set<String> h = new HashSet<String>(Arrays.asList("a", "b", "c")); 

但为什么? 我不觉得它比明确添加元素更可读。

使用Java 8(可修改集)

在Java 8中使用stream

 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)); 

使用Java 8(不可修改集)

如果我们对不可修改的集合感兴趣,那么我们有一个使用Collections.unmodifiableSet的选项:

 Set<String> strSet4 = Collections.unmodifiableSet(strSet1); 

但看起来有些尴尬,我们可以这样写我们自己的collections家:

 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::unmodifiableSet); } } 

然后用它作为:

 Set<String> strSet4 = Stream.of("Apple", "Ball", "Cat", "Dog") .collect(ImmutableCollector.toImmutableSet()); 

使用Java 9(不可修改集)

 Set<String> strSet5 = Set.of("Apple", "Ball", "Cat", "Dog"); 

如果你在集合中只有一个初始值就足够了:

 Set<String> h = Collections.singleton("a"); 

我觉得最可读的是简单地使用谷歌番石榴:

 Set<String> StringSet = Sets.newSet("a", "b", "c"); 

coobird的答案用于创build新的HashSet 的效用函数的推广:

 public static <T> Set<T> newHashSet(T... objs) { Set<T> set = new HashSet<T>(); for (T o : objs) { set.add(o); } return set; } 

最方便的方法之一是使用通用的Collections.addAll()方法,该方法需要一个集合和可变参数:

 Set<String> h = new HashSet<String>(); Collections.addAll(h, "a", "b"); 

如果Set的包含types是一个枚举,则存在java构build的工厂方法(自1.5开始):

 Set<MY_ENUM> MY_SET = EnumSet.of( MY_ENUM.value1, MY_ENUM.value2, ... ); 

使用Eclipse集合有几种不同的方法来初始化包含字符'a'和'b'的Set在一个语句中。 Eclipse集合包含对象和基本types的容器,所以我说明了除了两者的可变,不可变,同步和不可修改版本以外,如何使用Set<String>CharSet

 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集合的提交者。

使用Java 9,您可以执行以下操作:

 Set.of("a", "b"); 

你会得到一个包含元素的不可变的Set。 有关详情,请参阅此链接 。

有点令人费解,但从Java 5起作用:

 Set<String> h = new HashSet<String>(Arrays.asList(new String[] { "a", "b" })) 

使用助手方法使其可读:

 Set<String> h = asSet ("a", "b"); public Set<String> asSet(String... values) { return new HashSet<String>(java.util.Arrays.asList(values)); } 

请注意,无论您最终提到的是哪种方法,如果这是一个默认设置(通常不会被修改)(如您正在创build的库中的默认设置),最好遵循此模式:

 // 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; 

好处取决于您创build该类的实例的数量,以及更改默认值的可能性。

如果你决定遵循这个模式,那么你也可以select最具可读性的设置初始化方法。 由于不同方法之间效率的微小差异可能无关紧要,因为您只需要初始化一次即可。

 import com.google.common.collect.Sets; Sets.newHashSet("a", "b"); 

要么

 import com.google.common.collect.ImmutableSet; ImmutableSet.of("a", "b"); 

(丑)双Brace初始化没有副作用:

 Set<String> a = new HashSet<>(new HashSet<String>() {{ add("1"); add("2"); }}) 

但是在某些情况下,如果我们提到这是一个很好的嗅觉,使最终的集合变得不可变,那么它可能是非常有用的:

 final Set<String> a = Collections.unmodifiableSet(new HashSet<String>(){{ add("1"); add("2"); }}) 

随着java9和便捷工厂方法的发布,这可以以更简洁的方式进行:

 Set set2 = Set.of("a", "b", "c"); 

这是一个优雅的解决scheme:

 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); } }; } 

可以使用静态块进行初始化:

 private static Set<Integer> codes1= new HashSet<Integer>(Arrays.asList(new Integer[] { 1, 2, 3, 4})); private static Set<Integer> codes2 = new HashSet<Integer>(Arrays.asList(new Integer[] { 5, 6, 7, 8})); private static Set<Integer> h = new HashSet<Integer>(); static{ h.add(codes1); h.add(codes2); } 

Builder模式可能在这里使用。 今天我有同样的问题。 在哪里我需要设置变异操作返回给我的Set对象的引用,所以我可以将它传递给超类的构造函数,以便他们也可以继续添加到相同的集合,依次构build一个新的StringSetBuilderclosures设置子类刚刚build成。 我写的构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; } } 

注意addAll()add()方法,它们是Set返回Set.add()Set.addAll() 。 最后注意build()方法,它返回对构build器封装的Set的引用。 下面说明如何使用这个Set构build器:

 class ChildClass { 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()); } }