流中“先过滤后映射”和“先映射后过滤”的性能是否有所不同?

时间:2019-08-17 12:08:49

标签: java java-8 java-stream

我想知道什么更快:按字段过滤自定义对象,然后按其字段映射,反之亦然(先映射,然后过滤)。
最后,我通常希望将映射的字段收集到某个Collection中。

例如,最简单的Person类:

Contact

现在让我们来一个public class Person { String uuid; String name; String secondName; }

List<Person> persons

2 个答案:

答案 0 :(得分:6)

在此特定示例中,调用Person.getName()基本上没有花费,这没关系,您应该使用可读性最高的内容(并且之后的过滤甚至可能会稍快一些,因为TJ提到,映射操作是过滤操作的一部分

但是,如果映射操作成本很高,则首先过滤(如果可能)会更有效,因为流不必映射已过滤出的元素。

让我们举一个人为的例子:您有一个ID流,对于流中的每个偶数ID,您都必须执行http GET请求或数据库查询以获取由该ID标识的商品的详细信息(并且因此将ID映射到详细对象)。

假定流由一半的偶数ID和一半的奇数ID组成,并且每个请求花费相同的时间,则可以通过首先过滤将时间除以2。如果每个HTTP请求都花费1秒,并且您有60个ID,则通过首先过滤,您就可以从60秒变到30秒来完成同一任务,而且还可以减少网络和外部http API的费用。

答案 1 :(得分:1)

显然,性能完全取决于

  • 流式传输时您执行的复杂操作(您的业务逻辑)
  • 数据的复杂程度

让我们采取两种简单的情况

场景1

如果您的map函数需要执行一些复杂的操作,例如调用一些外部REST api来操纵流对象,那么在这种情况下,我建议先在map之前进行过滤,因为这样可以减少不必要的昂贵REST调用。 在这种方法中,当我们首先进行过滤时,显然它对所有匹配的对象执行了两次映射操作。

enter image description here

场景2

假定您需要首先基于一些外部REST API调用或函数来操纵数据流,然后根据该结果进行过滤。显然,在这种情况下,您需要先进行映射,然后再过滤流。 与之前的方法相比,该方法可能会稍快一些,因为映射操作是过滤操作的一部分

enter image description here