Note 1: To prevent the use of raw-types, I have opted to provide a generic type for each class that I mention below by using E
, representing an element of a Collection<E>
.
Note 2: This answer is subject to change; please edit this post if a typo has occurred.
什么是集合工厂方法?
Java 中的集合工厂方法是一种静态方法,它提供了一种初始化集合工厂的简单方法。不可变的 Collection<E>
.
由于是不可变的,因此不能在内部添加、删除或修改任何元素Collection<E>
初始化后。
在 Java 9 中,为以下接口提供了集合工厂方法:List<E>
, Set<E>
, and Map<K, V>
他们改进了什么?
直到 Java 9 为止,还没有简单、通用的方法来初始化Collection<E>
带有初始元素/键值条目。以前,开发人员需要按如下方式初始化它们(假设泛型类型E
, K
, and V
已替换为Integer
):
-
List<Integer>
- The following method is arguably the simplest to initialize a
List<Integer>
with initial elements, however the result is simply a view of a List<Integer>
; we are unable to add to or remove from this List<Integer>
, but we are still able to modify existing elements by using List#set
.
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
- If we wanted our
List<Integer>
to be entirely mutable, then we would have to pass it to the constructor of an ArrayList<Integer>
, for example:
List<Integer> mutableList = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
-
Set<Integer>
- A
Set<Integer>
required more code to initialize with initial elements than a List<Integer>
does (seeing as a List<Integer>
is required to initialize a Set<Integer>
with initial elements), which can be seen below.
Set<Integer> mutableSet = new HashSet<>(Arrays.asList(1, 2, 3, 4, 5));
-
Map<Integer, Integer>
- A
Map<Integer, Integer>
is arguably the most complicated to initialize with initial key-value entries; however, there are multiple ways to go about it.
- 一种方法是首先初始化一个空的
Map<Integer, Integer>
并简单地调用Map#put
添加键值条目。
- 另一种方法是使用带有两个大括号的匿名类,这仍然需要
Map#put
被称为。
我为什么要使用它们?
我认为集合工厂方法为开发人员提供了一种简洁的方法来初始化List<E>
, Set<E>
, or Map<K, V>
带有初始元素/键值条目,这可以通过下面的示例看到。
使用正确的语法是什么?
为简单起见,这些示例将替换泛型类型E
, K
, and V
with Integer
.
-
List<Integer>
-
List<Integer> list = List.of();
- 初始化一个空的、不可变的
List<Integer>
.
-
List<Integer> list = List.of(1);
- 初始化一个不可变的
List<Integer>
与一个元素。
-
List<Integer> list = List.of(1, 2);
- 初始化一个不可变的
List<Integer>
有两个元素。
-
List<Integer> list = List.of(1, 2, 3, 4, 5, ...);
- 初始化一个不可变的
List<Integer>
具有可变数量的元素。
-
Set<Integer>
-
Set<Integer> set = Set.of();
- 初始化一个空的、不可变的
Set<Integer>
.
-
Set<Integer> set = Set.of(1);
- 初始化一个不可变的
Set<Integer>
与一个元素。
-
Set<Integer> set = Set.of(1, 2);
- 初始化一个不可变的
Set<Integer>
有两个元素。
-
Set<Integer> set = Set.of(1, 2, 3, 4, 5, ...);
- 初始化一个不可变的
Set<Integer>
具有可变数量的元素。
-
Map<Integer, Integer>
-
Map<Integer, Integer> map = Map.of();
- 初始化一个空的、不可变的
Map<Integer, Integer>
.
-
Map<Integer, Integer> map = Map.of(1, 2);
- 初始化一个不可变的
Map<Integer, Integer>
具有一个键值条目。
- 注意,关键是
1
其值为2
.
-
Map<Integer, Integer> map = Map.of(1, 2, 3, 4);
- 初始化一个不可变的
Map<Integer, Integer>
有两个键值条目。
- 请注意,按键是
1
and 3
值是2
and 4
.
-
Map<Integer, Integer> map = Map.ofEntries(Map.entry(1, 2), Map.entry(3, 4), ...);
- 初始化一个不可变的
Map<Integer, Integer>
具有可变数量的键值条目。
正如您所看到的,这种新的初始化方法比以前的方法需要更少的代码。
我可以使用集合工厂方法来创建可变对象吗?
The Collection<E>
由集合工厂方法创建的本质上是不可变的,但是我们可以将它们传递给实现的构造函数Collection<E>
生成可变版本:
-
List<Integer>
List<Integer> mutableList = new ArrayList<>(List.of(1, 2, 3, 4, 5));
-
Set<Integer>
Set<Integer> mutableSet = new HashSet<>(Set.of(1, 2, 3, 4, 5));
-
Map<Integer, Integer>
Map<Integer, Integer> mutableMap = new HashMap<>(Map.of(1, 2, 3, 4));