Java9:什么是集合工厂方法?
Java 9: What are collection factory methods?
Java 9 的到来为 Java 的集合 API 带来了许多新特性,其中之一就是集合工厂方法。
它们是什么以及如何正确实施它们?
注 1:为了防止使用原始类型,我选择为下面提到的每个 class 提供通用类型,方法是使用 E
,代表一个Collection<E>
.
的一个元素
注2:此答案可能会发生变化;如果出现拼写错误,请编辑此 post。
什么是集合工厂方法?
Java 中的集合工厂方法是一种静态方法,它提供了一种初始化 不可变 Collection<E>
.
的简单方法
是不可变的,Collection<E>
初始化后不能添加、删除或修改任何元素。
使用Java9,为以下接口提供集合工厂方法:List<E>
、Set<E>
和Map<K, V>
他们改进了什么?
直到 Java 9,还没有简单、通用的方法来初始化带有初始 elements/key-value 条目的 Collection<E>
。以前,开发人员需要按如下方式初始化它们(假设泛型类型 E
、K
和 V
已替换为 Integer
):
List<Integer>
- 下面的方法可以说是最简单的用初始元素初始化
List<Integer>
的方法,但是结果只是 List<Integer>
的一个视图;我们无法向 List<Integer>
添加或从中删除,但我们仍然可以使用 List#set
修改现有元素。
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
- 如果我们希望我们的
List<Integer>
完全可变,那么我们必须将它传递给 ArrayList<Integer>
的构造函数,例如:
List<Integer> mutableList = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
Set<Integer>
- A
Set<Integer>
比 List<Integer>
需要更多的代码来初始化初始元素(因为 List<Integer>
需要用初始元素初始化 Set<Integer>
) ,可以在下面看到。
Set<Integer> mutableSet = new HashSet<>(Arrays.asList(1, 2, 3, 4, 5));
Map<Integer, Integer>
- A
Map<Integer, Integer>
可以说是使用初始键值条目初始化最复杂的;但是,有多种方法可以解决这个问题。
- 一种方法是先初始化一个空的
Map<Integer, Integer>
,然后简单地调用 Map#put
来添加键值条目。
- 另一种方法是使用带有两个大括号的匿名 class,这仍然需要调用
Map#put
。
我为什么要使用它们?
我认为集合工厂方法为开发人员提供了一种使用初始 elements/key-value 条目初始化 List<E>
、Set<E>
或 Map<K, V>
的简洁方法,这可以通过下面的示例可以看出。
正确的语法是什么?
为简单起见,这些示例将用 Integer
.
替换泛型类型 E
、K
和 V
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>
。
- 注意key是
1
,value是2
.
Map<Integer, Integer> map = Map.of(1, 2, 3, 4);
- 用两个键值条目初始化不可变
Map<Integer, Integer>
。
- 请注意,键是
1
和 3
,值是 2
和 4
。
Map<Integer, Integer> map = Map.ofEntries(Map.entry(1, 2), Map.entry(3, 4), ...);
- 使用可变数量的键值条目初始化不可变
Map<Integer, Integer>
。
如您所见,这种新的初始化方法比它的前辈需要更少的代码。
我可以使用集合工厂方法来创建可变对象吗?
集合工厂方法创建的 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));
Java 9 的到来为 Java 的集合 API 带来了许多新特性,其中之一就是集合工厂方法。
它们是什么以及如何正确实施它们?
注 1:为了防止使用原始类型,我选择为下面提到的每个 class 提供通用类型,方法是使用 E
,代表一个Collection<E>
.
注2:此答案可能会发生变化;如果出现拼写错误,请编辑此 post。
什么是集合工厂方法?
Java 中的集合工厂方法是一种静态方法,它提供了一种初始化 不可变 Collection<E>
.
是不可变的,Collection<E>
初始化后不能添加、删除或修改任何元素。
使用Java9,为以下接口提供集合工厂方法:List<E>
、Set<E>
和Map<K, V>
他们改进了什么?
直到 Java 9,还没有简单、通用的方法来初始化带有初始 elements/key-value 条目的 Collection<E>
。以前,开发人员需要按如下方式初始化它们(假设泛型类型 E
、K
和 V
已替换为 Integer
):
List<Integer>
- 下面的方法可以说是最简单的用初始元素初始化
List<Integer>
的方法,但是结果只是List<Integer>
的一个视图;我们无法向List<Integer>
添加或从中删除,但我们仍然可以使用List#set
修改现有元素。List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
- 如果我们希望我们的
List<Integer>
完全可变,那么我们必须将它传递给ArrayList<Integer>
的构造函数,例如:List<Integer> mutableList = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
- 下面的方法可以说是最简单的用初始元素初始化
Set<Integer>
- A
Set<Integer>
比List<Integer>
需要更多的代码来初始化初始元素(因为List<Integer>
需要用初始元素初始化Set<Integer>
) ,可以在下面看到。Set<Integer> mutableSet = new HashSet<>(Arrays.asList(1, 2, 3, 4, 5));
- A
Map<Integer, Integer>
- A
Map<Integer, Integer>
可以说是使用初始键值条目初始化最复杂的;但是,有多种方法可以解决这个问题。- 一种方法是先初始化一个空的
Map<Integer, Integer>
,然后简单地调用Map#put
来添加键值条目。 - 另一种方法是使用带有两个大括号的匿名 class,这仍然需要调用
Map#put
。
- 一种方法是先初始化一个空的
- A
我为什么要使用它们?
我认为集合工厂方法为开发人员提供了一种使用初始 elements/key-value 条目初始化 List<E>
、Set<E>
或 Map<K, V>
的简洁方法,这可以通过下面的示例可以看出。
正确的语法是什么?
为简单起见,这些示例将用 Integer
.
E
、K
和 V
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>
。 - 注意key是
1
,value是2
.
- 用一个键值对初始化一个不可变的
Map<Integer, Integer> map = Map.of(1, 2, 3, 4);
- 用两个键值条目初始化不可变
Map<Integer, Integer>
。 - 请注意,键是
1
和3
,值是2
和4
。
- 用两个键值条目初始化不可变
Map<Integer, Integer> map = Map.ofEntries(Map.entry(1, 2), Map.entry(3, 4), ...);
- 使用可变数量的键值条目初始化不可变
Map<Integer, Integer>
。
- 使用可变数量的键值条目初始化不可变
如您所见,这种新的初始化方法比它的前辈需要更少的代码。
我可以使用集合工厂方法来创建可变对象吗?
集合工厂方法创建的 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));