我需要创建一个具有初始值的集合。

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

是否有一种方法可以在一行代码中做到这一点?例如,它对于最终的静态字段很有用。


当前回答

在Java 8中,我会使用:

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

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

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

其他回答

创建新哈希集时,coobird的answer效用函数的概括:

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

有几种方法:

双大括号初始化

这是一种创建匿名内部类的技术,它有一个实例初始化器,在创建实例时将string添加到自身:

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

请记住,这实际上会在每次使用HashSet时创建一个新的子类,尽管不必显式地编写一个新的子类。

一种实用方法

编写一个返回Set的方法并不是太难写:

public static Set<String> newHashSet(String... strings) {
    HashSet<String> set = new HashSet<String>();

    for (String s : strings) {
        set.add(s);
    }
    return set;
}

上面的代码只允许使用String类型,但是允许使用任何使用泛型的类型应该不会太难。

利用图书馆

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

例如,谷歌Collections有一个Sets.newHashSet(T…)方法,该方法将用特定类型的元素填充HashSet。

如果你正在寻找最紧凑的初始化集合的方法,那么在Java9中:

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

===================== 下面详细的回答 ==========================

使用Java 10(不可修改的集合)

Set<String> strSet1 = Stream.of("A", "B", "C", "D")
         .collect(Collectors.toUnmodifiableSet());

在这里,收集器实际上会返回Java 9中引入的不可修改的集合,这可以从源代码中的语句set -> (set <T>) set. of(set. toarray())中明显看出。

需要注意的一点是Collections.unmodifiableSet()方法返回指定集合的不可修改视图(根据文档)。不可修改的视图集合是不可修改的集合,也是备份集合上的视图。注意,对备份集合的更改仍然是可能的,如果发生更改,则通过不可修改的视图可见。但是在Java 10中,collections . tounmodifiableset()方法返回的是真正不可变的集合。


使用Java 9(不可修改的集合)

下面是最紧凑的初始化集合的方法:

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

这个方便工厂方法有12个重载版本:

static <E> Set<E> of() static <E> Set<E> of(E e1) Set<E> of(E e1, E e2) / /……等等 static <E> Set<E> of(E…elem)

那么一个自然的问题是,当我们有var-args时,为什么我们需要重载版本?答案是:每个var-arg方法都在内部创建一个数组,重载版本将避免不必要的对象创建,也将从垃圾收集开销中节省我们。


使用Java 8(可修改的集合)

在Java 8中使用流。

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

我们可以这样使用Collections.unmodifiableSet():

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

但这看起来有点尴尬,我们可以像这样编写自己的收集器:

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

然后把它用作:

Set<String> strSet4 = Stream.of("A", "B", "C", "D")
             .collect(ImmutableCollector.toImmutableSet());

使用Collectors.collectingAndThen ()

另一种方法是使用collections . collectingandthen()方法,它允许我们执行额外的整理转换:

import static java.util.stream.Collectors.*;
Set<String> strSet5 = Stream.of("A", "B", "C", "D").collect(collectingAndThen(
   toCollection(HashSet::new),Collections::unmodifiableSet));

如果我们只关心Set,那么我们也可以使用collections . toset()来代替collections . tocollection (HashSet::new)。

还可以检查Java 8的这个答案。

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

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

这是可变的。

你也可以使用vavr:

import io.vavr.collection.HashSet;

HashSet.of("a", "b").toJavaSet();