我有以下示例代码:
System.out.println(
"Result: " +
Stream.of(1, 2, 3)
.filter(i -> {
System.out.println(i);
return true;
})
.findFirst()
.get()
);
System.out.println("-----------");
System.out.println(
"Result: " +
Stream.of(1, 2, 3)
.flatMap(i -> Stream.of(i - 1, i, i + 1))
.flatMap(i -> Stream.of(i - 1, i, i + 1))
.filter(i -> {
System.out.println(i);
return true;
})
.findFirst()
.get()
);
1
Result: 1
-----------
-1
0
1
0
1
2
1
2
3
Result: -1
Tl;Dr,这已经在JDK-8075939中解决,并在Java ;10中修复(并在JDK-8225328中回传到Java 8)。
在研究实现(referencePipeline.java
)时,我们看到方法[link]
@Override
final void forEachWithCancel(Spliterator<P_OUT> spliterator, Sink<P_OUT> sink) {
do { } while (!sink.cancellationRequested() && spliterator.tryAdvance(sink));
}
将为findfirst
操作调用。需要特别注意的是sink.cancellationRequested()
,它允许在第一次匹配时结束循环。比较[link]
@Override
public final <R> Stream<R> flatMap(Function<? super P_OUT, ? extends Stream<? extends R>> mapper) {
Objects.requireNonNull(mapper);
// We can do better than this, by polling cancellationRequested when stream is infinite
return new StatelessOp<P_OUT, R>(this, StreamShape.REFERENCE,
StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT | StreamOpFlag.NOT_SIZED) {
@Override
Sink<P_OUT> opWrapSink(int flags, Sink<R> sink) {
return new Sink.ChainedReference<P_OUT, R>(sink) {
@Override
public void begin(long size) {
downstream.begin(-1);
}
@Override
public void accept(P_OUT u) {
try (Stream<? extends R> result = mapper.apply(u)) {
// We can do better that this too; optimize for depth=0 case and just grab spliterator and forEach it
if (result != null)
result.sequential().forEach(downstream);
}
}
};
}
};
}
因为这不仅仅是一个优化的事情,因为它意味着当子流是无限的时候代码就会中断,我希望开发人员很快证明他们“可以做得更好”…
为了说明其中的含义,虽然stream.iterate(0,I->i+1).findfirst()
按预期工作,但stream.of("“).FlatMap(X->stream.iterate(0,I->i+1)).findfirst()
将以无限循环结束。
关于该规范,可以在
…懒惰也允许在没有必要的时候避免检查所有的数据;对于“查找第一个长度超过1000个字符的字符串”这样的操作,只需要检查足够的字符串,以找到具有所需特征的字符串,而不需要检查源中所有可用的字符串。(当输入流是无限大的而不仅仅是大的时,这种行为变得更加重要。)
…
此外,一些操作被认为是短路操作。如果一个中间操作在提供无限的输入时可能产生有限的流,那么它就是短路的。如果一个终端操作在无限输入的情况下可能在有限时间内终止,那么它就是短路操作。在管道中具有短路操作是无限流处理在有限时间内正常终止的必要条件,但不是充分条件。
很明显,短路操作并不能保证有限时间的终止,例如,当一个滤波器不匹配任何处理不能完成的项目时,但是一个通过简单地忽略一个操作的短路性质而不支持有限时间内的任何终止的实现是远远不符合规范的。
对于Java流,有没有理由使用而不是和的组合? 例如使用: 或
我无法理解弹性搜索中的 Bool 筛选器和 And 筛选器之间的区别。 上下文:假设我的文档具有字段:X、Y、Z。 每个字段可以有多个值。 目标: 我想在以下意义上向弹性搜索发送一个查询:(X=value eX1 OR X=value eX2)AND(Y=value eY1 OR Y=value eY2 OR…)AND(Z=value eZ1 OR Z=value eZ2 OR……) 尝试: 我是
问题内容: 在这里使用Spring Framework … 我创建了一个过滤器来更改css文件的响应正文,如果直接调用url,它将运行。但是,如果匹配urlrewrite规则,则将跳过过滤器。 示例: 在web.xml中: urlrewrite.xml中有一个类似的映射设置: (出于多种原因,我们需要这样做) 因此,任何路径以w /“ / styles-special /”开头的 .css文件都将
问题内容: ,它在它的第一个版本,也有类似的代码如下: 通过使用惰性过滤器集合,它可以过滤满足给定谓词的前5个元素(在这种情况下,可以被3整除),而不必求值数组中的 每个 元素。 但是,答案随后表明,每个元素可以多次调用’谓词(对于范围为1 … 15的元素,其谓词为3次,结果为0,则为两次)。 懒惰评估此过滤器效率低下的原因是什么?有什么方法可以避免多次评估同一元素? 问题答案: 问题所在 这里的
通过一组转换进行筛选和按键分组: 关于如何让它更好的性能,有什么想法吗?谢谢你的帮助!