我需要创建一个带有初始值的Set
。
Set<String> h = new HashSet<String>();
h.add("a");
h.add("b");
有没有一种方法可以用一行代码完成这个操作?例如,对于最终的静态字段非常有用。我需要创建一个带有初始值的Set
。
Set<String> h = new HashSet<String>();
h.add("a");
h.add("b");
有没有一种方法可以用一行代码完成这个操作?例如,对于最终的静态字段非常有用。我有一个缩写,虽然不太节省时间,但适合单行显示:
Set<String> h = new HashSet<>(Arrays.asList("a", "b"));
再次强调,这种方法不够高效,因为你需要构造一个数组,将其转换为列表,然后再用该列表创建一个集合。
当初始化静态 final 集合时,我通常会按照以下方式编写:
public static final String[] SET_VALUES = new String[] { "a", "b" };
public static final Set<String> MY_SET = new HashSet<>(Arrays.asList(SET_VALUES));
稍微好看一点,对于静态初始化来说效率并不重要。
Set<String> h = Set.of("a", "b") //Unmodifiable
创建的集合是不可修改的。此答案截至2021年9月1日为准。 - Mark Peschel集合字面量原计划在Java 7中推出,但未能实现。因此目前还没有自动化的选项。
您可以使用guava的Sets
:
Sets.newHashSet("a", "b", "c")
或者你可以使用以下语法,它会创建一个匿名类,但是这种方法有点hacky:
Set<String> h = new HashSet<String>() {{
add("a");
add("b");
}};
如果你正在寻找初始化set的最紧凑方式,那么在Java9
中有一个方法:
Set<String> strSet = Set.of("Apple", "Ball", "Cat", "Dog");
Set<String> strSet1 = Stream.of("A", "B", "C", "D")
.collect(Collectors.toUnmodifiableSet());
在这里,收集器实际上会返回Java 9中引入的不可修改的集合,如源代码中的语句set -> (Set<T>)Set.of(set.toArray())
所示。
需要注意的一点是方法Collections.unmodifiableSet()
返回指定集合的不可修改视图(根据文档)。一个不可修改的视图集合是一个不可修改的集合,也是一个基于后备集合的视图。请注意,对后备集合的更改可能仍然是可能的,如果发生更改,则可以通过不可修改的视图看到它们。但是,方法Collectors.toUnmodifiableSet()
在Java 10中返回真正的不可变集合。
以下是初始化集合的最简洁方式:
Set<String> strSet6 = Set.of("Apple", "Ball", "Cat", "Dog");
然后自然而然地会问一个问题为什么我们需要过载版本,当我们有var-args时? 答案是:每个var-arg方法在内部创建一个数组,而具有重载版本将避免不必要的对象创建,并且还将保存我们免于垃圾收集开销。
static <E> Set<E> of()
static <E> Set<E> of(E e1)
static <E> Set<E> of(E e1, E e2)
// ....和其他
static <E> Set<E> of(E... elems)
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));
我们可以使用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()
,它允许我们执行额外的完成转换:
import static java.util.stream.Collectors.*;
Set<String> strSet5 = Stream.of("A", "B", "C", "D").collect(collectingAndThen(
toCollection(HashSet::new),Collections::unmodifiableSet));
Set
,那么我们也可以使用Collectors.toSet()
替换Collectors.toCollection(HashSet::new)
。Set.of()
的未来读者添加一个警告。如果您尝试添加重复元素,它将抛出IllegalArgumentException
异常。 - Snehasish在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));
Set
,可以创建一个 Singleton
:final Set<T> SOME_SET = Collections.singleton(t);
。 - Valentin GrégoireSet<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
,但使用泛型可以轻松实现对任何类型的使用。
使用库
许多库都有方便的方法来初始化集合对象。
例如,Google Collections 有一个名为 Sets.newHashSet(T...)
的方法,可将特定类型的元素填充到一个 HashSet
中。
ImmutableSet.of(T...)
。大多数情况下,如果您不需要稍后更改集合,则使用不可变集合有许多优势。 - Kevin Bourrillion最方便的一种方式是使用通用的 Collections.addAll() 方法,该方法接受一个集合和可变参数:
Set<String> h = new HashSet<String>();
Collections.addAll(h, "a", "b");
Set<String> immutableSet = Collections.singleton("a");
new HashSet<>(Arrays.asList( _values_ ))
方法来处理单个值。 - yokeho我认为最易读的方法就是简单地使用Google Guava:
Set<String> StringSet = Sets.newHashSet("a", "b", "c");
它是可变的。
Sets.newHashSet()
。 - membersound你可以在Java 6中完成这项任务:
Set<String> h = new HashSet<String>(Arrays.asList("a", "b", "c"));
但为什么呢?我并不觉得这比显式添加元素更易读。
new HashSet<String>("a", "b", "c");
,那么它会更易读。 - sam boosalis
initialCapacity
设置为集合的确切大小将会效率低下,因为它会强制立即重新哈希,除非您也考虑到loadFactor
。 - jaco0646