Spliterator - 大小旗帜与小型旗帜

Spliterator - sized vs subsized flags

https://docs.oracle.com/javase/8/docs/api/java/util/Spliterator.html

SIZED Characteristic value signifying that the value returned from estimateSize() prior to traversal or splitting represents a finite size that, in the absence of structural source modification, represents an exact count of the number of elements that would be encountered by a complete traversal.

SUBSIZED Characteristic value signifying that all Spliterators resulting from trySplit() will be both SIZED and SUBSIZED.

  1. 是否存在SIZED标志为on而SUBSIZED标志为off的情况?
  2. 是否存在SUBSIZED标志为on但SIZED标志为off的情况?

SpliteratorSIZED 但不是 SUBSIZED 的典型示例是从 HashMap 创建的 Spliterator。它将在其内部条目数组上保持一个范围,其中一些数组条目为 null,因为容量高于实际大小。要跳过的 null 个条目的确切分布取决于包含的键的哈希码。

所以 Spliterator 一开始确实知道它的(总)大小,但是在拆分范围时,它不知道每个范围中有多少个元素。 HashMap 的元素越多,大致平衡拆分的可能性就越大,所以这个策略是合理的,但是具体的子大小是未知的,需要对数组进行迭代才能找出。

在没有 SIZED 的情况下报告 SUBSIZED 特征毫无意义,据我所知,甚至无效。

有点晚了,但还是..这也让我前段时间感到困惑。我会列举我知道的那些:

HashMap(如上所述),因此 IdentityHashMapLinkedHashMapTreeMap

这里要注意的是ConcurrentHashMap不在列表中,因为它允许并发更新,所以它的大小实际上是通话的那一刻。事实上 CHM 甚至没有报告 SIZED 很明显。

然后是与 Map 相关的那些,例如 HashSetTreeSet,因为在内部它们仍然是地图。

然后在 BitSetBitSetSpliterator#characteristics 看起来像这样:

    @Override
    public int characteristics() {
        // Only sized when root and not split
        return (root ? Spliterator.SIZED : 0) |
            Spliterator.ORDERED | Spliterator.DISTINCT | Spliterator.SORTED;
    }

这可能看起来很有趣,但解释是:

// Raise the index of this spliterator to be the next set bit
// from the mid point
index = nextSetBit(mid, wordIndex(hi - 1));

所以对于 BitSet 这只会发生一次并且报告 SUBSIZED 没有意义,因为分裂不会正好发生在中间。

另一种方式完全没有意义:报告 SUBSIZED 而不是 SIZED,所以没有人(据我查看代码)那样做。