似乎我很难理解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());
}
控制台仅打印
4
。 StringBuilder
对象仍然具有值""
。当我添加过滤器操作时:
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/