阅读了有关Java 8的一些知识后,我进入了这篇博客文章,解释了有关流及其还原的一些知识,以及何时有可能使还原短路。在底部,它指出:
请注意,在findFirst或的情况下,findAny我们只需要与谓词匹配的第一个值(尽管findAny不能保证返回第一个)。但是,如果流没有排序,则我们的findFirst行为应类似于findAny。的操作allMatch,noneMatch并且anyMatch可能不会短路,因为在所有它的流可能需要评估所有的值,以确定操作者是否是true或false。因此,使用它们的无限流可能不会终止。
findFirst
findAny
allMatch
noneMatch
anyMatch
true
false
我知道这一点,findFirst或者findAny可能会缩短还原,因为一旦找到一个元素,就无需进一步处理。
但是,为什么这是不可能的allMatch,noneMatch和anyMatch?对于allMatch,如果找到与谓词不匹配的谓词,则可以停止处理。一样没有。而且anyMatch尤其是没有道理给我,因为它几乎等于findAny(除了返回什么)?
也可以这样说,这三个可能不会短路,因为它可能需要评估所有值findFirst/Any。
findFirst/Any
我缺少一些根本的区别吗?我不是很了解发生了什么吗?
有一个细微的差异,因为anyMatchfamily使用谓词,而findAnyfamily不使用谓词。从技术上findAny()看起来anyMatch(x -> true)和anyMatch(pred)看起来一样filter(pred).findAny()。因此,这里有另一个问题。考虑我们有一个简单的无限流:
findAny()
anyMatch(x -> true)
anyMatch(pred)
filter(pred).findAny()
Stream<Integer> s = Stream.generate(() -> 1);
因此,确实如此,应用于findAny()此流将始终短路并完成,而anyMatch(pred)取决于谓词。但是,让我们过滤无限流:
Stream<Integer> s = Stream.generate(() -> 1).filter(x -> x < 0);
产生的流也无限吗?这是一个棘手的问题。它实际上不包含任何元素,但是要确定该元素(例如使用.iterator().hasNext()),我们必须检查无限数量的基础流元素,因此该操作将永远不会完成。我也将这种流称为无限。但是,同时使用此类流anyMatch并findAny永远不会完成:
.iterator().hasNext()
Stream.generate(() -> 1).filter(x -> x < 0).anyMatch(x -> true); Stream.generate(() -> 1).filter(x -> x < 0).findAny();
因此findAny()也不能保证完成,这取决于先前的中间流操作。
总而言之,我认为该博客文章具有误导性。我认为,在官方JavaDoc中可以更好地解释无限流的行为。