如何直接初始化一个 HashMap(以字面量方式)

如何直接初始化一个 HashMap(以字面量方式)

技术背景

在 Java 开发中,HashMap 是常用的集合类之一,用于存储键值对。在某些场景下,我们希望能够以简洁的字面量方式直接初始化 HashMap,就像初始化数组一样方便,不过 Java 并没有像其他语言那样直接提供 HashMap 字面量语法,但在不同版本的 Java 中有不同的实现方式。

实现步骤

所有版本

若仅需一个键值对,可使用 Collections.singletonMap("key", "value")

Java 9 及更高版本

Java 9 增加了一些工厂方法来简化 Map 的创建:

  • Map.of 方法(适用于最多 10 个元素)
1
2
3
4
Map<String, String> test1 = Map.of(
"a", "b",
"c", "d"
);
  • Map.ofEntries 方法(适用于任意数量元素)
1
2
3
4
5
import static java.util.Map.entry;
Map<String, String> test2 = Map.ofEntries(
entry("a", "b"),
entry("c", "d")
);

生成的 Map 是不可变的,若需要可变的 Map,可复制一份:

1
Map<String, String> mutableMap = new HashMap<>(Map.of("a", "b"));

Java 8 及以下版本

  • 使用匿名子类初始化器
1
2
3
4
Map<String, String> myMap = new HashMap<String, String>() {{
put("a", "b");
put("c", "d");
}};

不过匿名子类可能会带来一些问题,如增加内存消耗、磁盘空间消耗和启动时间,以及可能持有外部类的引用影响垃圾回收。

  • 使用函数初始化
1
2
3
4
5
6
7
8
Map<String, String> myMap = createMap();

private static Map<String, String> createMap() {
Map<String, String> myMap = new HashMap<String, String>();
myMap.put("a", "b");
myMap.put("c", "d");
return myMap;
}
  • 使用 Guava 库
1
2
3
import com.google.common.collect.ImmutableMap;

Map<String, Integer> left = ImmutableMap.of("a", 1, "b", 2, "c", 3);

ImmutableMap.of 最多支持 5 个键值对,否则使用构建器:

1
2
3
4
Map<String, String> map = new ImmutableMap.Builder<String, String>()
.put("a", "a")
.put("b", "b")
.build();
  • 使用 Java 8 的流和收集器
1
2
3
4
5
6
7
8
9
10
import static java.util.stream.Collectors.toMap;
import java.util.AbstractMap.SimpleEntry;
import java.util.Map;
import java.util.stream.Stream;

Map<String, String> myMap = Stream.of(
new SimpleEntry<>("key1", "value1"),
new SimpleEntry<>("key2", "value2"),
new SimpleEntry<>("key3", "value3")
).collect(toMap(SimpleEntry::getKey, SimpleEntry::getValue));

核心代码

Java 9 及以上版本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import java.util.Map;

public class MapInitializationJava9 {
public static void main(String[] args) {
// 使用 Map.of
Map<String, String> test1 = Map.of(
"a", "b",
"c", "d"
);
System.out.println(test1);

// 使用 Map.ofEntries
import static java.util.Map.entry;
Map<String, String> test2 = Map.ofEntries(
entry("a", "b"),
entry("c", "d")
);
System.out.println(test2);

// 转换为可变 Map
Map<String, String> mutableMap = new HashMap<>(Map.of("a", "b"));
mutableMap.put("e", "f");
System.out.println(mutableMap);
}
}

Java 8 及以下版本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Stream;
import static java.util.stream.Collectors.toMap;
import java.util.AbstractMap.SimpleEntry;

public class MapInitializationJava8 {
public static void main(String[] args) {
// 匿名子类初始化器
Map<String, String> myMap1 = new HashMap<String, String>() {{
put("a", "b");
put("c", "d");
}};
System.out.println(myMap1);

// 函数初始化
Map<String, String> myMap2 = createMap();
System.out.println(myMap2);

// 使用 Guava 库
import com.google.common.collect.ImmutableMap;
Map<String, Integer> left = ImmutableMap.of("a", 1, "b", 2, "c", 3);
System.out.println(left);

// 使用流和收集器
Map<String, String> myMap3 = Stream.of(
new SimpleEntry<>("key1", "value1"),
new SimpleEntry<>("key2", "value2"),
new SimpleEntry<>("key3", "value3")
).collect(toMap(SimpleEntry::getKey, SimpleEntry::getValue));
System.out.println(myMap3);
}

private static Map<String, String> createMap() {
Map<String, String> myMap = new HashMap<String, String>();
myMap.put("a", "b");
myMap.put("c", "d");
return myMap;
}
}

最佳实践

  • 优先使用 Java 9 及以上版本的 Map.ofMap.ofEntries 方法,因为它们语法简洁,且不可变的 Map 在多线程环境下更安全。
  • 在 Java 8 及以下版本,若对性能和内存要求不高,可使用匿名子类初始化器;若需要避免匿名子类的问题,可使用函数初始化或 Guava 库。
  • 处理大量元素时,使用 Map.ofEntries 方法。

常见问题

  • Map.ofMap.ofEntries 生成的 Map 不可变:若需要可变的 Map,需复制一份。
  • Collectors.toMap 不支持 null:会抛出 NullPointerException,可使用自定义收集器解决。
1
2
3
4
5
6
7
8
Map<String, String> myMap = Stream.of(
new SimpleEntry<>("key1", "value1"),
new SimpleEntry<>("key2", (String) null),
new SimpleEntry<>("key3", "value3"),
new SimpleEntry<>("key1", "value1updated")
).collect(HashMap::new,
(map, entry) -> map.put(entry.getKey(), entry.getValue()),
HashMap::putAll);
  • 匿名子类的性能问题:使用匿名子类初始化器时,要注意其可能带来的性能和内存问题。

如何直接初始化一个 HashMap(以字面量方式)
https://119291.xyz/posts/how-to-directly-initialize-a-hashmap-in-a-literal-way/
作者
ww
发布于
2025年5月28日
许可协议