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

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

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


当前回答

创建新哈希集时,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;
}

其他回答

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

Builder模式在这里可能有用。今天我也遇到了同样的问题。在这里,我需要Set变异操作来返回Set对象的引用,因此我可以将它传递给超类构造函数,这样它们也可以通过依次构造一个新的StringSetBuilder来继续添加到相同的Set,脱离子类刚刚构建的Set。我写的构建器类看起来像这样(在我的例子中,它是一个外部类的静态内部类,但它也可以是它自己的独立类):

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

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

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

集合字面值计划在Java 7中使用,但最终没有加入。所以还没有自动的东西。

你可以使用番石榴的套装:

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

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

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

有几种方法:

双大括号初始化

这是一种创建匿名内部类的技术,它有一个实例初始化器,在创建实例时将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。

你可以在Java 6中做到:

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

但是为什么呢?我不认为它比显式地添加元素更具有可读性。