java - 深入了解分离器特性

标签 java java-8 java-stream spliterator

为了尝试深入理解java流和分割器,我对有一些微妙的问题。分流器特性 :

Q1:Stream.empty()对比 Stream.of() (Stream.of() 不带参数)

  • Stream.empty() : 超大尺寸
  • Stream.of() :缩小,不可变 , 尺寸, 已订购

  • 为什么Stream.empty()不具有与 Stream.of() 相同的特征?请注意,它在与 Stream.concat() 结合使用时会产生影响(特别是没有 ORDERED )。我会说 Stream.empty()不仅应该具有 IMMUTABLE 和 ORDERED,还应该具有 DISTINCT 和 NONNULL。也有道理 Stream.of()只有一个参数具有 DISTICT。

    Q2:LongStream.of()没有 NONNULL

    刚刚注意到 NONNULL 在 LongStream.of 中不可用.
    不是NONNULL所有LongStream的主要特征s, IntStream s 和 DoubleStream ?

    Q3:LongStream.range(,)对比 LongStream.range(,).boxed()
  • LongRange.range(,) :缩小,不可变,非空 , 尺码, 订购, 排序,不同
  • LongStream.range(,).boxed() : 超大尺寸、已定尺寸、已订购

  • 为什么.boxed()失去所有这些特征?它不应该失去任何东西。

    我明白 .mapToObj()可能会丢失 NONNULL、IMMUTABLE 和 DISTICT,但是 .boxed() ……没意义。

    Q4:.peek()失去 IMMUTABLE 和 NONNULL
    LongStream.of(1) : SUBSIZED, IMMUTABLE, NONNULL, SIZED, ...LongStream.of(1).peek() : 超大、超大、...

    为什么.peek()失去这些特性? .peek真的不应该失去任何东西。

    Q5:.skip() , .limit()丢失 SUBSIZED、IMMUTABLE、NONNULL、SIZED

    请注意,这些操作丢失了 SUBSIZED、IMMUTABLE、NONNULL、SIZED。为什么?如果尺寸可用,那么计算最终尺寸也很容易。

    Q6:.filter()失去 IMMUTABLE, NONNULL

    请注意,此操作也会丢失 SUBSIZED、IMMUTABLE、NONNULL、SIZED。丢失 SUBSIZED 和 SIZED 是有意义的,但其他两个没有意义。为什么?

    如果有人深入了解拆分器可以带来一些清晰度,我将不胜感激。谢谢。

    最佳答案

    我不得不承认,当我第一次尝试找出这些特性的实际含义时,我也遇到了困难,并且感觉它们的含义在 Java 8 的实现阶段没有明确确定,因此使用不一致。

    考虑 Spliterator.IMMUTABLE :

    Characteristic value signifying that the element source cannot be structurally modified; that is, elements cannot be added, replaced, or removed, so such changes cannot occur during traversal.



    在这个列表中看到“替换”很奇怪,在谈到 List 时,这通常不被认为是结构修改。或数组,因此,流和拆分器工厂接受数组(未克隆)报告 IMMUTABLE , 喜欢 LongStream.of(…)Arrays.spliterator(long[]) .

    如果我们把这更宽泛地解释为“只要不被客户端观察到”,则与CONCURRENT 没有显着差异。 ,因为在任何一种情况下,某些元素将被报告给客户端,而无法识别它们是在遍历期间添加的,还是由于删除而未报告的,因为无法倒带拆分器并进行比较。

    规范继续:

    A Spliterator that does not report IMMUTABLE or CONCURRENT is expected to have a documented policy (for example throwing ConcurrentModificationException) concerning structural interference detected during traversal.



    这是唯一相关的事情,一个拆分器报告,IMMUTABLECONCURRENT , 保证永远不会抛出 ConcurrentModificationException .当然,CONCURRENT排除 SIZED语义上,但这对客户端代码没有影响。

    事实上,这些特性并没有用于 Stream API 中的任何东西,因此,不一致地使用它们永远不会在某处引起注意。

    这也是为什么每次中间操作都有清除CONCURRENT的效果的解释。 , IMMUTABLENONNULL特性:Stream 实现不使用它们,其内部表示流状态的类不维护它们。

    同样,NONNULL不在任何地方使用,因此某些流的缺失没有任何影响。我可以找到 LongStream.of(…)问题归结为 Arrays.spliterator(long[], int, int) 的内部使用委托(delegate)给
    Spliterators.spliterator​(long[] array, int fromIndex, int toIndex, int additionalCharacteristics) :

    The returned spliterator always reports the characteristics SIZED and SUBSIZED. The caller may provide additional characteristics for the spliterator to report. (For example, if it is known the array will not be further modified, specify IMMUTABLE; if the array data is considered to have an encounter order, specify ORDERED). The method Arrays.spliterator(long[], int, int) can often be used instead, which returns a spliterator that reports SIZED, SUBSIZED, IMMUTABLE, and ORDERED.



    注意(再次)IMMUTABLE 的不一致使用特征。它再次被视为必须保证没有任何修改,同时,Arrays.spliterator反过来 Arrays.streamLongStream.of(…)将举报 IMMUTABLE特性,即使通过规范,也不能保证调用者不会修改他们的数组。除非我们考虑将元素设置为不是结构修改,但是,整个区别再次变得无意义,因为数组不能在结构上修改。

    并且明确指出没有NONNULL特征。虽然很明显原始值不能是 null ,以及 Spliterator.Abstract<Primitive>Spliterator类总是注入(inject)一个 NONNULL特征,Spliterators.spliterator​(long[],int,int,int) 返回的拆分器不继承自 Spliterator.AbstractLongSpliterator .

    不好的是,这不能在不改变规范的情况下解决,好的是,无论如何它没有任何后果。

    因此,如果我们忽略 CONCURRENT 的任何问题, IMMUTABLE , 或 NONNULL ,没有任何后果,我们有
    SIZEDskip & limit .这是一个众所周知的问题,结果 skiplimit已由 Stream API 实现。其他实现是可以想象的。这也适用于无限流与 limit 的组合。 ,它应该具有可预测的大小,但考虑到当前的实现,却没有。

    合并Stream.concat(…)Stream.empty() .空流不会对结果顺序施加约束,这听起来很合理。但是Stream.concat(…)当只有一个输入没有订单时释放订单的行为是值得怀疑的。请注意,在订购方面过于激进并不是什么新鲜事,请参阅 this Q&A关于首先被认为是故意的行为,但后来在 Java 8 更新 60 中被修复。也许,Stream.concat也应该在这个时候讨论……
    .boxed()的行为很容易解释。当它像 .mapToObj(Long::valueOf) 这样天真地实现时,它只会丢失所有知识,如 mapToObj不能假设结果仍然是排序的或不同的。但这已通过 Java 9 修复。那里,LongStream.range(0,10).boxed()SUBSIZED|SIZED|ORDERED|SORTED|DISTINCT特性,维护所有与实现相关的特性。

    关于java - 深入了解分离器特性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46644595/

    相关文章:

    java - 传递一个非关联函数来减少

    java - 使用 lambda 在函数中传递两个参数

    java - 如何在 Maven 中获取特定分支的 SVN 内部版本号

    java - Jersey 客户端语法错误请求错误

    java - 无法反序列化 lambda

    java - JAVA中如何组合两种方法?

    用于 int 范围的 Java 8 IntStream?

    java - 过滤掉 CompletableFuture 的重复项

    java - 如何在混淆的 java 文件中找出导致它的原因?

    java - Java中局部最终变量的行为