# 问题

35. Map.of() 方法创建的不可变集合有什么限制?

# 标准答案

Map.of() 是 Java 9 引入的一个用于创建不可变映射(Map)的方法,它允许简洁地初始化 Map 对象。它提供了一种方式来创建小型的、不可变的映射,特别适用于常量映射的场景。然而,使用 Map.of() 方法创建的集合存在一些限制和注意事项。

# 1. 不可变性

使用 Map.of() 创建的映射是不可变的。它的核心特性是,一旦创建,这个映射就不能被修改。不能添加、删除或更改映射中的键值对。如果尝试进行这些操作,将会抛出 UnsupportedOperationException

例如:

Map<String, Integer> map = Map.of("a", 1, "b", 2);
map.put("c", 3);  // 抛出 UnsupportedOperationException
map.remove("a");  // 抛出 UnsupportedOperationException
1
2
3

# 2. 键值对数量限制

Map.of() 方法可以创建一个包含最多 10 个键值对的映射。如果想要创建更多的键值对,可以使用 Map.ofEntries() 方法,它允许传递任意数量的键值对。

  • Map.of() 适用于最多 10 个键值对:
    • Map.of():创建一个空映射。
    • Map.of(K k1, V v1):创建一个包含一个键值对的映射。
    • Map.of(K k1, V v1, K k2, V v2):创建一个包含两个键值对的映射,依此类推。

例如:

Map<String, Integer> map = Map.of("a", 1, "b", 2, "c", 3, "d", 4, "e", 5, "f", 6, "g", 7, "h", 8, "i", 9, "j", 10);
1

超过 10 个键值对时,你需要使用 Map.ofEntries()

# 3. 键和值的限制

  • 键和值不能为 null:使用 Map.of() 时,传入的键和值不能为空(null)。如果传入 null 值或键,会抛出 NullPointerException

例如:

Map<String, Integer> map = Map.of("a", 1, "b", null);  // 抛出 NullPointerException
Map<String, Integer> map = Map.of(null, 1);  // 抛出 NullPointerException
1
2

# 4. 性能

虽然 Map.of() 提供了创建不可变映射的简单方法,但它的性能上并不适合动态修改的场景。由于其不可变的特性,每次尝试修改映射都会抛出异常,因此它是用于常量集合或需要频繁查找但不需要修改的场景。

# 5. 适用场景

Map.of() 适合用于需要初始化固定且小型键值对集合的场景。例如,它在处理常量映射、配置属性、返回预定义数据等方面非常有用。

# 示例

Map<String, Integer> map = Map.of("apple", 1, "banana", 2, "cherry", 3);

// 访问元素
System.out.println(map.get("apple"));  // 输出 1

// 尝试修改元素
map.put("orange", 4);  // 抛出 UnsupportedOperationException
1
2
3
4
5
6
7

在这个示例中,map 是通过 Map.of() 创建的,它是不可变的,任何修改操作都会导致异常。

# 6. Map.ofEntries()

如果需要更多的键值对,可以使用 Map.ofEntries(),它允许传递任意数量的 Map.Entry 对象。

Map<String, Integer> map = Map.ofEntries(
    Map.entry("apple", 1),
    Map.entry("banana", 2),
    Map.entry("cherry", 3)
);
1
2
3
4
5

Map.ofEntries() 提供了更灵活的方式来构建不可变映射,并支持更多的键值对。

# 总结

Map.of() 方法创建的不可变映射有以下限制:

  • 不可修改:不能添加、删除或修改映射中的键值对。
  • 键和值不能为 null
  • 键值对数量有限Map.of() 最多支持 10 个键值对,超过此限制应使用 Map.ofEntries()
  • 适用于常量映射:适合用于需要初始化固定、不可变映射的场景。

# 核心原理

Map.of() 创建的映射是不可变的,所有的操作(如修改、删除)都被明确禁止,以确保它们是不可变的。它是利用 Java 集合的 Collections.unmodifiableMap() 来保证不可变性。

# 深入追问

🔹 Map.of()Map.ofEntries() 的区别有哪些? 🔹 Map.of() 是否会影响性能?如何判断是否适合使用它?

# 相关面试题

  • Map.of() 方法适用于哪些场景?
  • 如何使用 Map.ofEntries() 初始化一个大于 10 个键值对的映射?
  • 为什么 Map.of() 创建的映射是不可变的?