java - 为什么 Map.of 不允许空键和值?

标签 java dictionary null hashmap java-9

在 Java 9 中,为 ListSetMap 接口(interface)引入了新的工厂方法。这些方法允许使用一行中的值快速实例化 Map 对象。现在,如果我们考虑:

Map<Integer, String> map1 = new HashMap<Integer, String>(Map.of(1, "value1", 2, "value2", 3, "value3"));
map1.put(4, null);

如果我们这样做,则无一异常(exception)地允许上述情况:

Map<Integer, String> map2 = Map.of(1, "value1", 2, "value2", 3, "value3", 4, null );

它抛出:

Exception in thread "main" java.lang.NullPointerException
    at java.base/java.util.Objects.requireNonNull(Objects.java:221)
..

我无法得到,为什么在第二种情况下不允许使用 null

我知道 HashMap 可以将 null 作为键和值,但为什么在 Map.of 的情况下会受到限制?

同样的事情发生在 java.util.Set.of("v1", "v2", null)java.util.List.of("v1 ", "v2", null).

最佳答案

正如其他人指出的那样,the Map contract允许拒绝空值...

[S]ome implementations prohibit null keys and values [...]. Attempting to insert an ineligible key or value throws an unchecked exception, typically NullPointerException or ClassCastException.

...和收集工厂(不只是在 map 上)make use of that .

They disallow null keys and values. Attempts to create them with null keys or values result in NullPointerException.

但是为什么呢?

在集合中允许 null 现在被视为设计错误。这有多种原因。一个好的是可用性,其中最突出的麻烦制造者是 Map::get。如果它返回 null,则不清楚是缺少键还是值是 null。一般来说,保证 null 免费的集合更容易使用。在实现方面,它们还需要较少的特殊大小写,从而使代码更易于维护且性能更高。

你可以听 Stuart Marks 解释 in this talk但是 JEP 269 (介绍工厂方法的那个)也总结了一下:

Null elements, keys, and values will be disallowed. (No recently introduced collections have supported nulls.) In addition, prohibiting nulls offers opportunities for a more compact internal representation, faster access, and fewer special cases.

由于 HashMap 在慢慢被发现时已经被广泛使用,因此在不破坏现有代码的情况下更改它为时已晚,但这些接口(interface)的最新实现(例如 ConcurrentHashMap )没有不再允许null,工厂方法的新集合也不异常(exception)。

(我认为另一个原因是显式使用 null 值被视为可能的实现错误,但我错了。那是要复制键,这也是非法的。)

所以不允许 null 有一些技术原因,但这样做也是为了提高使用创建的集合的代码的健壮性。

关于java - 为什么 Map.of 不允许空键和值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45210398/

相关文章:

java - 如何正确实现 ListIterator 的中间模型?

java.lang.UnsupportedOperationException 但没有 Arrays.asList()

arrays - 遍历 Go 中的任意可迭代数据结构

react-native-mapbox-gl/maps 如何更改样式?

java - Exoplayer 的 Ooyala SDK - NoClassDefFoundError : com. ooyala.android.player.exoplayer.ExoStreamPlayer

java - 调用 Action 事件

c# - 为什么 HttpSessionState 不实现 IDictionary?

c# - SQL Datareader 空值

c++ - 在 C++ 中使用模板时返回 NULL

html - 当提交的表单字段为空时,mysql中的双数据类型存储null