2015-08-24 73 views
10

关于Java 8读了一下,我得this博客文章,解释了一下关于流和减少他们的,当它有可能短路的减少。在底部它规定:在findFirstfindAny的情况下Java的8个流短路

报告中,我们只需要相匹配的谓词(尽管findAny不保证返回第一个)的第一个值。但是,如果该流没有订购,那么我们预计findFirst的行为将类似于findAny。操作allMatchnoneMatchanyMatch可能不短路流,因为在所有可能需要评估所有的值,以确定操作者是否是truefalse。因此使用这些的无限流可能不会终止。

我得到findFirstfindAny可以减少短路,因为一旦自动对焦您找到一个元素,你不需要进一步处理任何。

但为什么这不可能为allMatch,noneMatchanyMatch?对于allMatch,如果找到与谓词不匹配的一个,则可以停止处理。没有。而anyMatch对我来说尤其没有意义,因为它几乎等于findAny(除了返回的内容)?

说,这三种可能不会短路,因为这可能会评估所有的值,也可以为findFirst/Any说。

我错过了一些基本的区别吗?我真的不明白发生了什么事吗?

+0

“可能不”,如“可能不”,而不是“不允许”。 – Andreas

+0

@Andreas是的,我只是没有得到差异来自哪里。所有的东西都可以按照我看的方式进行短路? – Koekje

回答

12

有一个细微的差别,因为anyMatch家庭使用谓词,而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()),我们必须检查无限数量的底层流元素,因此此操作永远不会结束。我也会称这种流为无限的。但是使用这种流既anyMatchfindAny写不完:

Stream.generate(() -> 1).filter(x -> x < 0).anyMatch(x -> true); 
Stream.generate(() -> 1).filter(x -> x < 0).findAny(); 

所以findAny()不能保证完成要么,这取决于前面的中间流操作。

最后,我会认为这个博客文章非常具有误导性。在我看来,无限流行为在官方JavaDoc中有更好的解释。

+0

感谢您的解释! :) – Koekje

1

当的Javadoc说“可以不短路”它仅仅指出它不是一个短路操作,并根据这些值,则整个流可以被处理。

findFirstfindAny另一方面保证短路,因为一旦他们满意,他们不需要处理剩余的流。

+0

但是它也可能发生在谓词中,只要它们没有被满足? – Koekje

0

anyMatch,noneMatch和allMatch返回布尔值,所以他们可能要检查所有的证明逻辑。

findFirst和findAny只关心找到第一个他们可以并返回的。

编辑: 对于给定的数据集,Match方法保证始终返回相同的值,但Find方法并不是因为顺序可能会变化并影响返回的值。

描述的短路在谈论缺乏对于给定数据集的一致性查找方法。

+0

但anyMatch也可以吗? – Koekje

+0

如果最后的值是匹配,那么是的。 Point是Match方法将始终在同一数据集上返回相同的值,但Find方法无法保证一致性,因为顺序可能有所不同。 –

+0

缺少一致性的是短路描述 –

5

回答更新

我想说的博客文章是错误的,当它说“的FindFirst或findAny我们只需要其中的谓词匹配的第一个值”。

在Javadoc为allMatch(Predicate)anyMatch(Predicate)noneMatch(Predicate)findAny()findFirst()

这是一个短路端子的操作。

但是,请注意findFirstfindAny没有一个Predicate。所以他们都可以在看到第一个/任何值时立即返回。另外3个是有条件的,并且如果条件从不发生,可以永远循环。

+0

来自博客:“操作allMatch,noneMatch和anyMatch可能根本不会短路流,因为它可能需要评估所有值以确定操作符是否为真。 “这显然是不正确的,因为只要发现第一个不匹配,allMatch就可以被确定为false。 –

+0

@MisrableVariable正如我所说,博客文章是错误的。他们*可以*全部短路。 ---博客是正确的,他们中的三个可能*永远运行,但它说这一切都是错误的。 – Andreas

1

根据Oracle的文档流: https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html#StreamOps

终端操作是短路如果,当与无限输入呈现,其可以在有限时间内结束。在流水线中进行短路操作是处理无限流在有限时间内正常终止的必要但不充分的条件。

所有五个功能也行:

这是一个短路端子的操作。

在函数的描述中。

+0

感谢您的文档参考! – Koekje