4

我正在考虑这个问题的答案:如何在任何 Java 地图实现上测试空键?

我的第一个想法是检查Spliterator地图的键集是否具有以下特征Spliterator.NONNULL

map.keySet().spliterator().hasCharacteristics(Spliterator.NONNULL)

JavaDoc说:

表示源保证遇到的元素不会为空的特征值。(例如,这适用于大多数并发集合、队列和映射。)

在回答之前我做了一些检查:

没有提供的 Spliteratora不具有此特征,即使自然排序不允许空键。TreeMapCompararator

new TreeMap<>().keySet().spliterator().hasCharacteristics(Spliterator.NONNULL); // false 

更令人惊讶的是,键集Spliterator的 s本身并没有这个特性。EnumMapEnumSet

EnumSet.allOf(DayOfWeek.class).spliterator().hasCharacteristics(Spliterator.NONNULL); // false

我知道spliterator().hasCharacteristics(Spliterator.NONNULL)在上述情况下的结果返回false为默认实现Set.spliterator()被评估。

但是,这些集合的拆分器不覆盖Set.spliterator()创建Spliteratorwith是否有原因Spliterator.NONNULL?这会破坏我不知道的规范吗?

4

2 回答 2

4

更糟:

System.out.println(Set.of(1)
             .spliterator()
             .hasCharacteristics(Spliterator.NONNULL)); // false

即使这些Set::of方法被记录为:

如果元素为 null,则抛出 NullPointerException

所以没有办法以 null 结束Set。我想真正的答案是这还没有完成

编辑

请参阅Stuart Marks 对此的评论

于 2018-09-11T13:36:14.553 回答
3

但是,这些集合的拆分器不覆盖Set.spliterator()创建Spliteratorwith是否有原因Spliterator.NONNULL

我们只能推测,但可以肯定的是,某些TreeMap使用Comparators 进行排序的实例确实容纳了空键,因此它们的键集的拆分器必须没有特性Spliterator.NONNULL。尽管 aTreeMap使用其键的自然顺序确实不能容纳空键,但我个人并不感到惊讶的是,TreeMap的键集不使用它来进行区分。我希望这种属性完全由所涉及的类驱动,而不是由每个实例的详细信息驱动。

这会破坏我不知道的规范吗?

也许。 用于指定的文档Set.spliterator()

Spliterator报告Spliterator.DISTINCT。_ 实施应记录附加特征值的报告。

(添加了重点。) TreeMap.keySet() 的文档

该集合的拆分器是late-bindingfail-fast,并且另外报告Spliterator.SORTED并且Spliterator.ORDERED遇到顺序是升序键顺序。拆分器的比较器(参见 Spliterator.getComparator())是null如果树图的比较器(参见 SortedMap.comparator())是null。否则,拆分器的比较器与树形图的比较器相同或施加相同的总排序。

请注意,该集合的文档符合文档中的期望集合Set.spliterator(),即使有条件地指定,这Spliterator.NONNULL是键集拆分器将报告的特征之一。进一步注意,这些相同的文档确实描述了这些集合的其他特征,这些特征取决于地图的顺序是否基于比较器。

因此,不,您不应该期望密钥集的拆分器在任何情况下TreeMap都有报告。Spliterator.NONNULL我无法明确说明为什么会做出这个选择,但这与我对 Java 设计哲学的看法是一致的。

你还写道,

更令人惊讶的是, 键集Spliterator的 s本身并没有这个特性。EnumMapEnumSet

我同意这些分裂者可以合理地报告Spliterator.NONNULL。我不知道为什么选择他们不这样做,除非这只是一个疏忽。尽管如此,我观察到他们的文档确实没有指定这些拆分器将报告Spliterator.NONNULL. 在这种情况下,可以预期那些分离器不会报告该特征。

于 2018-09-11T14:15:24.263 回答