我在考虑一个问题的答案:如何在任何Java映射实现上测试空键?
我的第一个想法是检查地图的键集的Spliterator是否具有特征Spliterator.NONNULL。
map.keySet().spliterator().hasCharacteristics(Spliterator.NONNULL)JavaDoc说:
表示源保证遇到的元素不会为null的特征值。(例如,这适用于大多数并发集合、队列和映射。)
在回答之前,我做了一些检查:
没有提供Spliterator的TreeMap的Compararator不具有此特性,即使自然排序不允许空键。
new TreeMap<>().keySet().spliterator().hasCharacteristics(Spliterator.NONNULL); // false 更令人惊讶的是,Spliterator的EnumMap键集和EnumSet本身并不具有这一特性。
EnumSet.allOf(DayOfWeek.class).spliterator().hasCharacteristics(Spliterator.NONNULL); // false我了解到,在上述情况下,spliterator().hasCharacteristics(Spliterator.NONNULL)的结果将返回false,因为Set.spliterator()的默认实现是计算的。
但是,为什么这些集合的分割器不覆盖Set.spliterator()来创建带有Spliterator.NONNULL的Spliterator,有什么原因吗?这会违反我不知道的规范吗?
发布于 2018-09-11 13:36:14
更糟的是:
System.out.println(Set.of(1)
.spliterator()
.hasCharacteristics(Spliterator.NONNULL)); // false即使这些Set::of方法被记录为:
如果元素为空,则抛出NullPointerException。
因此,在那个Set中没有办法以null结尾。我想真正的答案是,这还没有完成。
编辑
发布于 2018-09-11 14:15:24
但是,为什么这些集合的分割器不覆盖
Set.spliterator()来创建带有Spliterator.NONNULL的Spliterator,有什么原因吗?
我们只能推测,但当然,使用Comparator进行排序的一些Comparator实例确实容纳了空键,因此它们的密钥集的分配器必须没有特征的Spliterator.NONNULL。虽然使用键的自然排序的TreeMap不能容纳空键,但我个人并不感到奇怪的是,TreeMap的键集不使用它来进行区分,这是我希望完全由所涉及的类驱动的属性,而不是每个实例的详细信息。
这会违反我不知道的规范吗?
也许吧。Set.spliterator()指定
Spliterator报道Spliterator.DISTINCT。实现应该记录附加特征值的报告。
(强调后加) TreeMap.keySet()的文档说
集合的分配器是延迟绑定、快速失败的,并且还使用升序键顺序报告
Spliterator.SORTED和Spliterator.ORDERED。如果树映射的比较器(参见Spliterator.getComparator())的比较器(参见SortedMap.comparator())为null,则分集器的比较器(参见SortedMap.comparator())为null。否则,分集器的比较器与树映射的比较器相同或施加相同的总顺序。
请注意,该集合的文档符合Set.spliterator()文档中的期望集,没有指定(甚至是有条件地)指定Spliterator.NONNULL是键集分集器将报告的特征之一。请进一步注意,这些文档确实描述了这些集合的其他特性,这些特性取决于映射的顺序是否基于比较器。
因此,不,您不应该期望TreeMap键集、分配器在任何情况下都会报告Spliterator.NONNULL。我无法确定为什么要做出这样的选择,但这与我对Java设计哲学的看法是一致的。
你还写过,
更令人惊讶的是,
Spliterator的EnumMap键集和EnumSet本身并不具有这一特性。
我同意这些分配器可以合理地报告Spliterator.NONNULL。我不知道为何他们会选择不这样做,除非这只是一种疏忽。尽管如此,我注意到他们的文档实际上并没有指定这些分配器将报告Spliterator.NONNULL。在这种情况下,预期这些分配器不会报告这种特性。
https://stackoverflow.com/questions/52276985
复制相似问题