我正在考虑以下问题的答案:How to test for null keys on any Java map implementation?
我的第一个想法是检查地图键集的checkValue(checkBox20,checkValue);
是否具有特征Spliterator
:
Spliterator.NONNULL
JavaDoc说:
特征值,表示来源保证 遇到的元素将不会为null。 (例如,这适用于 大多数并发的集合,队列和地图。)
在回答之前,我做了一些检查:
即使{em>自然排序不允许空键,map.keySet().spliterator().hasCharacteristics(Spliterator.NONNULL)
中Spliterator
的{{1}}也没有此特征。
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()
的{{1}}的原因?这会破坏我不知道的规范吗?
答案 0 :(得分:4)
更糟糕的是:
System.out.println(Set.of(1)
.spliterator()
.hasCharacteristics(Spliterator.NONNULL)); // false
即使这些Set::of
方法记录为:
如果元素为null,则抛出NullPointerException
因此,没有办法以该Set
结尾的null结尾。我想真正的答案是这还没有完成。
编辑
答案 1 :(得分:3)
但是,为什么有这些集合的分隔符不覆盖
Set.spliterator()
来创建具有Spliterator
的{{1}}的原因?
我们只能推测,但是肯定是某些使用Spliterator.NONNULL
进行排序的TreeMap
实例容纳了空键,因此它们的键集分隔符不能具有特征性的{{ 1}}。尽管使用其键自然排序的Comparator
确实不能容纳空键,但我个人并不感到惊讶Spliterator.NONNULL
的键集不使用它来进行区分。我希望这种属性完全由所涉及的类驱动,而不是由每个实例的细节驱动。
这会破坏我不知道的规范吗?
也许。 The docs for Set.spliterator()
指定
TreeMap
报告TreeMap
。 实施应记录其他特征值的报告。
(添加了强调。)The docs for TreeMap.keySet()说
集合的分隔符为 late-binding , fail-fast ,以及 报告
Spliterator
和Spliterator.DISTINCT
并遇到 升序为关键顺序的命令。分离器的比较器(请参见 如果树图的比较器,则Spliterator.SORTED
是Spliterator.ORDERED
(请参见Spliterator.getComparator()
是null
。否则,分离器的 比较器与的相同或施加相同的总排序 树图的比较器。
请注意,此集合的文档符合SortedMap.comparator()
文档中的期望集,甚至没有指定null
是密钥集的分隔符将报告的特征之一。还要注意,这些相同的文档 do 描述了这些集合的其他特征,这些特征根据地图的顺序是否基于比较器而有所不同。
因此,不,您不应该期望Set.spliterator()
键集的分隔符在任何情况下都具有报告Spliterator.NONNULL
。我无法确切地说出为什么要做出此选择,但这与我对Java设计哲学的看法是一致的。
您还写了
更令人惊讶的是,
TreeMap
中的Spliterator.NONNULL
个 键集和Spliterator
本身不具有此特征。
我同意这些分隔符可以合理地报告EnumMap
。我不知道为什么选择他们不这样做,除非这仅仅是一个疏忽。但是,我发现他们的文档确实没有指定这些分隔符将报告EnumSet
。在这种情况下,可以预期那些分离器将不会报告该特性。