Koe*_*kje 18 java short-circuiting java-8 java-stream
在Java 8上读了一下,我得到了这篇博文,解释了一些关于流和减少它们的内容,以及什么时候可以缩短缩减.在底部它表明:
注意在
findFirst
或者findAny
我们只需要与谓词匹配的第一个值(虽然findAny
不能保证返回第一个).但是如果流没有排序,那么我们期望findFirst
表现得像findAny
.的操作allMatch
,noneMatch
并anyMatch
可能不短路流,因为在所有可能需要评估所有的值,以确定操作者是否是true
或false
.因此,使用这些的无限流可能不会终止.
我得到了这个findFirst
或者findAny
可能会缩短减少量,因为一旦你找到了一个元素,你就不需要再进一步处理了.
但为什么这不可能allMatch
,noneMatch
并且anyMatch
?因为allMatch
,如果找到与谓词不匹配的一个,则可以停止处理.同样没有.而且anyMatch
尤其是没有道理给我,因为它几乎等于findAny
(除了返回什么)?
说这三个可能不会短路,因为它可能需要评估所有的值,也可以说findFirst/Any
.
我缺少一些根本区别吗?我真的不明白发生了什么事吗?
Tag*_*eev 19
有一个微妙的区别,因为anyMatch
家庭使用谓词,而findAny
家庭则没有.技术上findAny()
看起来像anyMatch(x -> true)
和anyMatch(pred)
看起来像filter(pred).findAny()
.所以这里有另一个问题.考虑一下我们有一个简单的无限流:
Stream<Integer> s = Stream.generate(() -> 1);
Run Code Online (Sandbox Code Playgroud)
因此,应用于findAny()
此类流将始终短路并完成,而应用anyMatch(pred)
取决于谓词.但是,让我们过滤我们的无限流:
Stream<Integer> s = Stream.generate(() -> 1).filter(x -> x < 0);
Run Code Online (Sandbox Code Playgroud)
结果流也是无限的吗?这是一个棘手的问题.它实际上不包含任何元素,但为了确定这一点(例如,使用.iterator().hasNext()
),我们必须检查无限数量的底层流元素,因此这个操作永远不会完成.我也称这种流为无限.但是使用这样的流anyMatch
并且findAny
永远不会完成:
Stream.generate(() -> 1).filter(x -> x < 0).anyMatch(x -> true);
Stream.generate(() -> 1).filter(x -> x < 0).findAny();
Run Code Online (Sandbox Code Playgroud)
所以findAny()
也不保证完成,这取决于之前的中间流操作.
总而言之,我认为该博客文章具有误导性.在我看来,在官方JavaDoc中更好地解释了无限流行为.
答案已更新
我说博客文章说"findFirst或findAny我们只需要与谓词匹配的第一个值"是错误的.
在allMatch(Predicate)的javadoc中,anyMatch(Predicate),noneMatch(Predicate),findAny()和findFirst():
这是一种短路终端操作.
但是,请注意findFirst
并且findAny
没有Predicate
.因此,他们可以在看到第一个/任何值后立即返回.其他3个是有条件的,如果条件永远不会触发,它可能永远循环.
根据Oracle的流文档: https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html#StreamOps
如果当提供无限输入时,终端操作可以在有限时间内终止,则该终端操作是短路的。管道中的短路操作是无限流处理在有限时间内正常终止的必要条件,但不是充分条件。
所有五个函数都有一行:
这是短路端子操作。
在函数的描述中。
归档时间: |
|
查看次数: |
7748 次 |
最近记录: |