Java 8 findFirst()。isPresent()比count()> 0更有效吗?

鉴于我有一个Stream stream = list.stream().filter(some predicate) ,其中列表非常大,通过执行以下stream.count() > 0来检查流是否为空是更有效的: stream.count() > 0或通过执行: stream.findFirst().isPresent()

如果你想知道的是,是否有匹配,你应该使用
list.stream().anyMatch(some predicate) ,不仅因为它更有效,而且因为它是表达你意图的正确习惯list.stream().anyMatch(some predicate)

正如其他人所说的那样, anyMatch是短路的,这意味着它会在第一场比赛时停止,而如名字所示,count将在返回之前统计所有比赛。 根据流内容,这可以产生巨大的性能差异。 但请注意,通过使用list.stream().filter(some predicate).limit(1).count() > 0可以使count效率相同list.stream().filter(some predicate).limit(1).count() > 0

然后,它也将在第一次出现后停止,但是, anyMatchanyMatch仍然是表达您是否有任何匹配感兴趣的首选方式。 当任务是要找出是否至少有 n匹配时,事情会发生变化。 然后, .limit(n).count() > n-1 (或>= n )成为自然的习语。

请注意, findFirst()与其他解决方案不同,因为它的答案取决于排序。 因此,如果您只想知道是否匹配,则应使用findAny()代替。 尽管如此,由于需要返回匹配值,与只是告诉是否存在匹配(如anyMatch所做的)相比,存在理论上的差异,尽管目前这种差异仅在于构造Optional实例,因此可以忽略不计。

但是,由于您正在针对API进行编程以编码您的意图,因此当您只想知道是否存在匹配时,不应使用find… anyMatch清楚地表达了您的意图,并且可能在将来的实现或更复杂的场景中具有更高的优势。

我建议使用list.stream().anyMatch(some predicate) ,这对于这种情况来说是一个终端操作。 它不仅比stream.count()更有效,而且它不会挂在无限流上。

findAny (如果你不需要命令,它比findFirst更好)和anyMatch是短路操作 ,这意味着如果条件允许,它们可以提前返回而不消耗整个流。 这是在他们的方法javadocs中提到并链接的。 count() 不是 。

如果流的最后阶段仍使用具有SIZED特征的分裂器,则count() 可能与其他两个选项一样快。 但这是一个比短路更弱的特性,因为中间流操作 – 例如filter() – 很可能会丢弃SIZED方面。

所有这些信息都可以从包文档中收集,强烈建议阅读。