我需要创建一个具有初始值的集合。
Set<String> h = new HashSet<String>();
h.add("a");
h.add("b");
是否有一种方法可以在一行代码中做到这一点?例如,它对于最终的静态字段很有用。
我需要创建一个具有初始值的集合。
Set<String> h = new HashSet<String>();
h.add("a");
h.add("b");
是否有一种方法可以在一行代码中做到这一点?例如,它对于最终的静态字段很有用。
当前回答
如果你正在寻找最紧凑的初始化集合的方法,那么在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");
这是可变的。
结合Michael Berdyshev的回答和泛型,并使用initialCapacity构造函数,与数组进行比较。asList变体:
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
@SafeVarargs
public static <T> Set<T> buildSetModif(final T... values) {
final Set<T> modifiableSet = new HashSet<T>(values.length);
Collections.addAll(modifiableSet, values);
return modifiableSet;
}
@SafeVarargs
public static <T> Set<T> buildSetModifTypeSafe(final T... values) {
return new HashSet<T>(Arrays.asList(values));
}
@SafeVarargs
public static <T> Set<T> buildeSetUnmodif(final T... values) {
return Collections.unmodifiableSet(buildSetModifTypeSafe(values));
// Or use Set.of("a", "b", "c") if you use Java 9
}
如果你为init传递一些值,这是很好的 使用其他方法 如果您不小心将类型与buildSetModif混合,则生成的T将 是什么?扩展对象,这可能不是你想要的,这不能发生在buildSetModifTypeSafe变体,这意味着buildSetModifTypeSafe(1,2, "a");不会编译
你也可以使用vavr:
import io.vavr.collection.HashSet;
HashSet.of("a", "b").toJavaSet();
有一个我使用的简写,不是很省时,但适合单行:
Set<String> h = new HashSet<>(Arrays.asList("a", "b"));
同样,这并不省时,因为您正在构造一个数组,转换为一个列表,并使用该列表创建一个集合。
当初始化静态最终集时,我通常这样写:
public static final String[] SET_VALUES = new String[] { "a", "b" };
public static final Set<String> MY_SET = new HashSet<>(Arrays.asList(SET_VALUES));
对于静态初始化来说,稍微不那么丑陋和效率并不重要。
有点复杂,但可以在Java 5中工作:
Set<String> h = new HashSet<String>(Arrays.asList(new String[] {
"a", "b"
}))
使用helper方法使其可读:
Set<String> h = asSet ("a", "b");
public Set<String> asSet(String... values) {
return new HashSet<String>(java.util.Arrays.asList(values));
}