java - 中级流操作未按计数进行评估

标签 java java-stream

似乎我很难理解Java如何将流操作组合到流管道中。

执行以下代码时

public
 static void main(String[] args) {
    StringBuilder sb = new StringBuilder();

    var count = Stream.of(new String[]{"1", "2", "3", "4"})
            .map(sb::append)
            .count();

    System.out.println(count);
    System.out.println(sb.toString());
}

控制台仅打印4StringBuilder对象仍然具有值""

当我添加过滤器操作时:filter(s -> true)
public static void main(String[] args) {
    StringBuilder sb = new StringBuilder();

    var count = Stream.of(new String[]{"1", "2", "3", "4"})
            .filter(s -> true)
            .map(sb::append)
            .count();

    System.out.println(count);
    System.out.println(sb.toString());
}

输出更改为:
4
1234

这种看似多余的过滤器操作如何改变合成流管道的行为?

最佳答案

在我的JDK版本中,count()终端操作最终执行以下代码:

if (StreamOpFlag.SIZED.isKnown(helper.getStreamAndOpFlags()))
    return spliterator.getExactSizeIfKnown();
return super.evaluateSequential(helper, spliterator);

如果在操作流水线中存在filter()操作,则不再知道最初知道的流的大小(因为filter可以拒绝该流的某些元素)。因此,不执行if块,执行中间操作,并因此修改StringBuilder。

另一方面,如果管道中只有map(),则可以保证流中的元素数与初始元素数相同。因此,如果执行了if块,则不评估中间操作就直接返回大小。

请注意,传递给map()的lambda违反了文档中定义的约定:它应该是无干扰的无状态操作,但并非无状态。因此,在两种情况下得出不同的结果都不能视为错误。

关于java - 中级流操作未按计数进行评估,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59592076/

相关文章:

java - JPA 查询 IN 子句对具有 CSV 值的列不返回准确的结果

java - 如何使用流将所有映射键值连接成一个字符串,并对每个值进行替换?

java - 使用 TiledMap 的 Libgdx 碰撞检测

java - 启用 Maven 与 eclipse 集成的步骤

java - 按字母顺序连接有关字段名称的对象值

java - 为什么要在 Java Stream 接口(interface)中重载 varargs 方法 of()?

java - 如何在 Java 流中配对不均匀列表

java - 如何从多个迭代器创建并行拆分器?

java - java中第二个jsp页面结果集为空时如何直接重定向到上一个jsp页面

java - 如何正确设置 Spring Tool Suite 的 JAVA HOME 环境变量?