没有特征Spliterator.NONNULL的EnumSet.spliterator

时间:2018-09-11 13:23:57

标签: java java-8 set spliterator

我正在考虑以下问题的答案: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}}的原因?这会破坏我不知道的规范吗?

2 个答案:

答案 0 :(得分:4)

更糟糕的是:

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

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

  

如果元素为null,则抛出NullPointerException

因此,没有办法以该Set结尾的null结尾。我想真正的答案是这还没有完成。

编辑

请参见comment from Stuart Marks about this

答案 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 ,以及   报告SpliteratorSpliterator.DISTINCT并遇到   升序为关键顺序的命令。分离器的比较器(请参见   如果树图的比较器,则Spliterator.SORTEDSpliterator.ORDERED(请参见   Spliterator.getComparator()null。否则,分离器的   比较器与的相同或施加相同的总排序   树图的比较器。

请注意,此集合的文档符合SortedMap.comparator()文档中的期望集,甚至没有指定null是密钥集的分隔符将报告的特征之一。还要注意,这些相同的文档 do 描述了这些集合的其他特征,这些特征根据地图的顺序是否基于比较器而有所不同。

因此,不,您不应该期望Set.spliterator()键集的分隔符在任何情况下都具有报告Spliterator.NONNULL。我无法确切地说出为什么要做出此选择,但这与我对Java设计哲学的看法是一致的。

您还写了

  

更令人惊讶的是,TreeMap中的Spliterator.NONNULL个   键集和Spliterator本身不具有此特征。

我同意这些分隔符可以合理地报告EnumMap。我不知道为什么选择他们不这样做,除非这仅仅是一个疏忽。但是,我发现他们的文档确实没有指定这些分隔符将报告EnumSet。在这种情况下,可以预期那些分离器将不会报告该特性。