如何直接初始化一个 HashMap(以字面量方式)
技术背景
在 Java 开发中,HashMap
是常用的集合类之一,用于存储键值对。在某些场景下,我们希望能够以简洁的字面量方式直接初始化 HashMap
,就像初始化数组一样方便,不过 Java 并没有像其他语言那样直接提供 HashMap
字面量语法,但在不同版本的 Java 中有不同的实现方式。
实现步骤
所有版本
若仅需一个键值对,可使用 Collections.singletonMap("key", "value")
。
Java 9 及更高版本
Java 9 增加了一些工厂方法来简化 Map
的创建:
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; }
|
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();
|
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<String, String> test1 = Map.of( "a", "b", "c", "d" ); System.out.println(test1);
import static java.util.Map.entry; Map<String, String> test2 = Map.ofEntries( entry("a", "b"), entry("c", "d") ); System.out.println(test2);
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);
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.of
和 Map.ofEntries
方法,因为它们语法简洁,且不可变的 Map
在多线程环境下更安全。 - 在 Java 8 及以下版本,若对性能和内存要求不高,可使用匿名子类初始化器;若需要避免匿名子类的问题,可使用函数初始化或 Guava 库。
- 处理大量元素时,使用
Map.ofEntries
方法。
常见问题
Map.of
和 Map.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);
|
- 匿名子类的性能问题:使用匿名子类初始化器时,要注意其可能带来的性能和内存问题。