Difference between estimatedSize and getExactSizeIfKnown in Spliterator

gho*_*der 5 java java-8 spliterator

I am trying to understand the features of Spliterator and came across these 2 methods estimatedSize and getExactSizeIfKnown I could figure out what is estimatedSize but not sure exactly what doesgetExactSizeIfKnowndo. Can someone please give an example explaining the difference between the two.

EDIT: I tried the following example in which both of them are the same. In which cases would they be different?

public static void main(String[] args) {
        List<Integer> l = new ArrayList<>();
        l.add(1);
        l.add(2);
        l.add(3);
        Spliterator<Integer> s= (Spliterator<Integer>) l.spliterator();
    Spliterator<Integer> s1=s.trySplit();
    while(s.tryAdvance(n -> {System.out.print(n+" ");System.out.println("estimateSize "+s.estimateSize()+" getexactsizeifknown "+s.getExactSizeIfKnown());})); 
Run Code Online (Sandbox Code Playgroud)

Sla*_*law 5

estimateSize方法:

返回forEachRemaining(java.util.function.Consumer<? super T>)遍历将遇到的元素数量的估计值,或者返回Long.MAX_VALUE无穷大,未知或过于昂贵而无法计算的元素。

如果此分割器已经SIZED并且尚未被部分遍历或拆分,或者此分割器已经SUBSIZED并且尚未被部分遍历,则此估计值必须是完整遍历会遇到的元素的准确计数。否则,此估算值可能是任意不正确的,但必须按照调用之间的指定减少trySplit()

API注意:

即使是不精确的估算值,也通常对计算有用且便宜。例如,近似平衡的二叉树的子拆分器可能返回一个值,该值估计元素的数量为其父代的一半。如果根分离器不能保持准确的计数,则可以将大小估计为与其最大深度相对应的2的幂。

getExactSizeIfKnown方法是:

estimateSize()如果此Spliterator为SIZEDelse ,则返回的便捷方法-1

实施要求:

默认实现返回estimateSize()如果Spliterator报告特性为的结果SIZED-1否则返回。

这两个方法都参考SIZED,这是:

表示estimateSize()遍历或分割之前返回的值的特征值表示有限大小,在没有结构源修改的情况下,该大小表示完整遍历将遇到的元素数的精确计数。

API注意:

集合的大多数拆分器,涵盖了Collection此特征的报告的所有元素。子分类器(例如用于HashSet的子分类器)不包含元素的子集并近似于其报告的大小。

基于所有这些,这两种方法只会在Spliterator不具有SIZED 特征的情况下返回不同的值。


在您的示例中,的来源SpliteratorArrayList。如果我们看一下以下文档ArrayList.spliterator()

在此列表中的元素上创建后期绑定和故障Spliterator转移。

Spliterator报告Spliterator.SIZEDSpliterator.SUBSIZEDSpliterator.ORDERED。首要实现应记录其他特征值的报告。

由于该SUBSIZED特性,SpliteratorArrayList-所创建的-包括由-所产生的那些trySplit-将永远不会具有estimateSizegetExactSizeIfKnown返回不同的值。

  • @ghostrider由HashSet返回的分离器_after_调用trySplit。换句话说,HashSet的子分隔符返回-1。至少在Java 12中。 (2认同)
  • @ghostrider停留在您的问题示例中,`Spliterator &lt;Integer&gt; s = l.stream()。filter(x-&gt; true).spliterator();出于明显的原因不知道其确切大小,但是提供了一个估计值。Slaw的示例也适用于Java 8到Java 12。如[此答案](/sf/answers/3136194911/)中所述(在下半部分),当使用范围分割哈希图的内部数组时,它取决于元素的实际分布(根据(它们的哈希码)),则每个部分中有多少个元素,因此大小变成了估算值。 (2认同)