我的世界奥特曼模组手机版[百度网盘资源]
1.78 GB · 2025-11-14
JDK 9 新变化之 Convenience Factory Methods for Collections以下方法都是 JDK 9 中新增的。
List.of(...)(这里用 ... 表示我们不关心参数的类型/数量,下同)Set.of(...)Map.of(...)Map.ofEntries(...)详细的描述可以参考 JEP 269: Convenience Factory Methods for Collections(本文的很多内容都参考了它)。在本文中,我会在 JEP 269: Convenience Factory Methods for Collections 的基础上,谈谈自己的理解。
以下方法都是 JDK 9 中新增的。有了这些方法,我们可以方便地创建包含少量元素(或者 key-value pair)的 List/Set/Map。这些方法调用起来很直观,而且它们底层的结构也比较简单。
List.of(...)Set.of(...)Map.of(...)Map.ofEntries(...)List.of(...) 的思维导图如下 ⬇️
mindmap
Root("List.of(...)")
List12
node11("参数中的元素数是1或2时,<br/>List.of(...) 返回 List12 的实例")
node12("List12 中用 e0, e1 两个字段<br/>来保存所有的元素")
ListN
node21("参数中的元素数是0或大于等于3时,<br/>List.of(...) 返回 ListN 的实例")
ListN 使用 elements 字段来保存所有的元素
Set.of(...) 的思维导图如下 ⬇️
mindmap
Root("Set.of(...)")
Set12
node11("参数中的元素数是1或2时,<br/>Set.of(...) 返回 Set12 的实例")
node12("Set12 使用 e0, e1 两个字段<br/>来保存所有的元素")
SetN
node21("参数中的元素数是0或大于等于3时,<br/>Set.of(...) 返回 SetN 的实例")
node22("SetN 使用 elements 字段来保存所有的元素")
node23("SetN 使用 开放寻址法(open addressing)<br/>来访问元素")
Map.of(...)/Map.ofEntries(...) 的思维导图如下 ⬇️
mindmap
Root("Map.of(...)/Map.ofEntries(...)")
Map1
node11("待处理的 key-value pair 的个数是1时,<br/>Map.of(...)/Map.ofEntries(...) 返回 Map1 的实例")
node12("Map1 使用 k0, v0 两个字段<br/>来保存仅有的 key-value pair")
MapN
node21("待处理的 key-value pair 的个数不等于1时,<br/>Map.of(...)/Map.ofEntries(...) 返回 MapN 的实例")
node22("MapN 使用 table 字段来保存所有的 key 和 value")
node23("MapN 使用 开放寻址法(open addressing)<br/>来访问 key-value pair")
在 JDK 9 之前,如果我们想创建一个只包含 "a", "b", "c" 3 个元素的 set,可能会采用以下几种做法(这几种做法的代码均来自 JEP 269: Convenience Factory Methods for Collections)。
Set<String> set = new HashSet<>();
set.add("a");
set.add("b");
set.add("c");
set = Collections.unmodifiableSet(set);
如果是对静态字段赋值,需要将这样的代码写在静态初始化块里(因为这样的代码没法在一个表达式里写完)。
Set<String> set = Collections.unmodifiableSet(new HashSet<>(Arrays.asList("a", "b", "c")));
第二种做法会额外创建 List 对象。
Set<String> set = Collections.unmodifiableSet(new HashSet<String>() {{
add("a"); add("b"); add("c");
}});
第三种做法利用了匿名内部类。
Set<String> set = Collections.unmodifiableSet(Stream.of("a", "b", "c").collect(toSet()));
第四种做法利用了 Java 8 提供的 Stream API。
以上四种做法都包含了不少代码,我们只是想创建一个小的 set 而已,如果可以不用写这么多代码就好了。
List/Set/Map?java.util.Collections 类中在更早的时候已经提供了相关的方法 ⬇️
调用 java.util.Collections 类中的哪个静态方法? | 得到的是哪个类的实例? | |
|---|---|---|
如何创建空的 List | Collections.emptyList() | java.util.Collections$EmptyList |
如何创建空的 Set | Collections.emptySet() | java.util.Collections$EmptySet |
如何创建空的 Map | Collections.emptyMap() | java.util.Collections$EmptyMap |
key-value pair)的 List/Set/Map?java.util.Collections 类中在更早的时候已经提供了相关的方法 ⬇️
调用 java.util.Collections 类中的哪个静态方法? | 得到的是哪个类的实例? | |
|---|---|---|
如何创建单元素的 List | Collections.singletonList(T) | java.util.Collections$SingletonList |
如何创建单元素的 Set | Collections.singleton(T) | java.util.Collections$SingletonSet |
如何创建只包含一个 key-value pair 的 Map | Collections.singletonMap(K, V) | java.util.Collections$SingletonMap |
JDK 9如果在 List/Set/Map 中可以提供一些静态方法,让我们可以创建含有任意多个元素(或 key-value pair)的 List/Set/Map 就好了。例如对 List/Set 而言,我们希望可以写出如下的代码。
List.of(a, b, c);
Set.of(d, e, f, g);
如果 List.of(...)/Set.of(...) 系列的方法中有支持变长参数的的版本,那么我们就可以为任意数量的元素生成对应的 List/Set。
对 Map 而言,如果可以用如下的代码来生成包含少量 key-value pair 的 Map 的话,将会很方便。
Map.of()
Map.of(k1, v1)
Map.of(k1, v1, k2, v2)
Map.of(k1, v1, k2, v2, k3, v3)
...
如果 key-value pair 的数量比较多的话,那么 Map.of(...) 将无法支持(因为 JVM 中对方法的参数个数的上限有约束)。此时,如果有如下的方法,那么也算差强人意。
Map.ofEntries(Map.Entry<K,V>...)
我们可以这样调用 ⬇️
Map.ofEntries(
Map.entry(k1, v1),
Map.entry(k2, v2),
Map.entry(k3, v3),
// ... entry(kn, vn));
JDK 9 中确实新增了这些方法 ⬇️
List.of(...)Set.of(...)Map.of(...)Map.ofEntries(...)List.of(...) 返回的是以下两个类的实例 ⬇️
java.util.ImmutableCollections$List12java.util.ImmutableCollections$ListNSet.of(...) 返回的是以下两个类的实例 ⬇️ (更多细节可以参考我写的另一篇文章:[Java] 浅析 Set.of(...) 方法)
java.util.ImmutableCollections$Set12java.util.ImmutableCollections$SetNMap.of(...)/Map.ofEntries(...) 返回的是以下两个类的实例 ⬇️ (更多细节可以参考我写的另一篇文章:[Java] 浅析 Map.of(...) 方法和 Map.ofEntries(...) 方法)
java.util.ImmutableCollections$Map1java.util.ImmutableCollections$MapN其中
List12/Set12/Map1 中用字段来保存元素(或者 key-value pair)
List12 使用 e0, e1 两个字段来保存所有元素Set12 使用 e0, e1 两个字段来保存所有元素Map1 使用 k0, v0 两个字段来保存仅有的那个 key-value pairListN/SetN/MapN 中用数组来保存元素(或者 key-value pair)
ListN 使用 elements 字段来保存所有元素SetN 使用 elements 字段来保存所有元素,并通过 开放寻址法(open addressing) 来访问它们MapN 使用 table 字段来保存所有的 key 和 value,并通过 开放寻址法(open addressing) 来访问它们List12/ListN/Set12/SetN/Map1/MapN 的类图如下 ⬇️
请注意:以下的类/接口在类图中被忽略了
java.io.SerializableclassDiagram
Iterable <|-- Collection
Collection <|.. AbstractCollection
AbstractCollection <|-- AbstractImmutableCollection
Collection <|-- SequencedCollection
SequencedCollection <|-- List
AbstractImmutableCollection <|-- AbstractImmutableList
List <|.. AbstractImmutableList
RandomAccess <|.. AbstractImmutableList
AbstractImmutableList <|-- List12
AbstractImmutableList <|-- ListN
Collection <|-- Set
AbstractImmutableCollection <|-- AbstractImmutableSet
Set <|.. AbstractImmutableSet
AbstractImmutableSet <|-- Set12
AbstractImmutableSet <|-- SetN
Map <|.. AbstractMap
AbstractMap <|-- AbstractImmutableMap
AbstractImmutableMap <|-- Map1
AbstractImmutableMap <|-- MapN
<<Abstract>> AbstractCollection
<<Abstract>> AbstractImmutableCollection
<<Abstract>> AbstractImmutableList
<<Abstract>> AbstractImmutableSet
<<Abstract>> AbstractMap
<<Abstract>> AbstractImmutableMap
<<interface>> Iterable
<<interface>> Collection
<<interface>> SequencedCollection
<<interface>> List
<<interface>> RandomAccess
<<interface>> Set
<<interface>> Map
| 在上图中的类名/接口名 | Fully Qualified Name |
|---|---|
AbstractCollection | java.util.AbstractCollection |
AbstractImmutableCollection | java.util.ImmutableCollections$AbstractImmutableCollection |
AbstractImmutableList | java.util.ImmutableCollections$AbstractImmutableList |
AbstractImmutableMap | java.util.ImmutableCollections$AbstractImmutableMap |
AbstractImmutableSet | java.util.ImmutableCollections$AbstractImmutableSet |
AbstractMap | java.util.AbstractMap |
Collection | java.util.Collection |
Iterable | java.lang.Iterable |
List | java.util.List |
List12 | java.util.ImmutableCollections$List12 |
ListN | java.util.ImmutableCollections$ListN |
Map | java.util.Map |
Map1 | java.util.ImmutableCollections$Map1 |
MapN | java.util.ImmutableCollections$MapN |
RandomAccess | java.util.RandomAccess |
SequencedCollection | java.util.SequencedCollection |
Set | java.util.Set |
Set12 | java.util.ImmutableCollections$Set12 |
SetN | java.util.ImmutableCollections$SetN |
我在 [Java] 如何自动生成简单的 Mermaid 类图 一文中分享过可以生成简单 Mermaid 类图的代码,在那些代码的基础上,可以通过执行如下的命令来生成类图 ⬇️
java ClassDiagramGenerator -i 'java.io.Serializable' 'java.util.ImmutableCollections$List12' 'java.util.ImmutableCollections$ListN' 'java.util.ImmutableCollections$Set12' 'java.util.ImmutableCollections$SetN' 'java.util.ImmutableCollections$Map1' 'java.util.ImmutableCollections$MapN'
1.78 GB · 2025-11-14
1.98 GB · 2025-11-14
12.33MB · 2025-11-14