java - Stream中“先过滤后映射”和“先映射后过滤”的性能是否不同?
问题描述
我想知道什么更快:按字段过滤自定义对象,然后按其字段映射,反之亦然(映射然后过滤)。
最后,我通常想将映射的字段收集到一些集合中。
例如最简单的 Person 类:
public class Person {
String uuid;
String name;
String secondName;
}
现在让我们有一个List<Person> persons
.
List<String> filtered1 = persons
.stream()
.filter(p -> "NEED_TOY".equals(p.getName()))
.map(Person::getName)
.collect(Collectors.toList());
// or?
List<String> filtered2 = persons
.stream()
.map(Person::getName)
.filter(p -> "NEED_TOY".equals(p))
.collect(Collectors.toList());
解决方案
在这个具体的例子中,调用Person.getName()
基本上没有成本,没关系,你应该使用你认为最易读的东西(并且过滤之后甚至可以稍微快一点,因为正如 TJ 提到的那样,映射操作是一部分的过滤操作)。
但是,如果映射操作的成本很高,那么首先过滤(如果可能)会更有效,因为流不必映射已过滤掉的元素。
让我们举一个人为的例子:你有一个 ID 流,对于流中的每个偶数 ID,你必须执行一个 http GET 请求或一个数据库查询来获取由这个 ID 标识的项目的详细信息(从而映射ID 到详细对象)。
假设流由一半偶数和一半奇数组成,并且每个请求花费相同的时间,您可以通过先过滤将时间除以 2。如果每个 http 请求需要 1 秒,并且您有 60 个 ID,那么通过先过滤,您可以将同一任务从 60 秒缩短到 30 秒,并且还可以减少网络和外部 http API 的费用。
推荐阅读
- python - 计算来自巨大 csv 文件的唯一行数
- websocket - Rouille中websocket的高CPU使用率
- java - 一段时间后无法连接 Cassandra [无法连接到任何主机,计划在 10000 毫秒内重试]
- python - 如何覆盖在 pytest 4 中调用原始设备的 pytest 夹具
- python - 如何在 Python 中结合积分方程?
- html - 移除 DataTable 的下边框
- javascript - 如何比较两个对象并返回不同的对象
- c# - IdentityServer4 和 Azure AD 在登录页面上自动选择用户
- python - 为数据过滤器提高我的 pyspark 程序的性能
- r - 从 lda 对象恢复原始文档 ID