java - 带有两个列表的 Java 8 流
问题描述
我有一个方法需要 2 个列表作为参数,正如您在方法主体中看到的那样,我想做一些过滤并将结果返回给调用者。我想用 lambda 表达式将此代码转换为 Java 8 流,但我想不通。我最终为此创建了多个流,这超出了重构的目的(恕我直言)。我想知道的是,我如何以一种简单的方式将其重构为一个流?
public Set<CustomerTrack> getCustomerTracks(List<CusomerTrack> tracks, List<Customer> customers) {
Set<CustomerTrack> tracksToSave = new HashSet<>();
for (Customer customer : customers) {
if (customer.getTrack() == null) {
continue;
}
Long allowedTrackId = customer.getTrack().getId();
for (CustomerTrack track : tracks) {
if (Long.valueOf(track.getId()).equals(allowedTrackId)) {
tracksToSave.add(track);
}
}
}
return tracksToSave;
}
解决方案
似乎这就是你所追求的:
customers.stream()
.filter(c -> c.getTrack() != null)
.map(c -> c.getTrack().getId())
.flatMap(id -> tracks.stream().filter(track -> Long.valueOf(track.getId()).equals(id)))
.collect(Collectors.toSet());
请注意,对于每个id
您都在迭代整个 ; 列表tracks
。这很O(n*m)
复杂。这通常被认为很糟糕,您可以改进它。
为了使它更好,您首先要从;创建一个HashSet
id 。Customer
有了它,HashSet
您现在contains
可以使用您感兴趣的 id 来调用它,因为contains
它的时间复杂度为O(1)
(它实际上被称为摊销复杂度O(1)
)。所以现在你的复杂性变成了O(n)
+ O(1)
,但是因为O(1)
它是一个常数,它真的O(n)
- 比你以前的要好得多。在代码中:
Set<Long> set = customers.stream()
.filter(c -> c.getTrack() != null)
.map(c -> c.getTrack().getId())
.collect(Collectors.toSet());
Set<CusomerTrack> tracksToSave = tracks.stream()
.filter(track -> set.contains(track.getId())
.collect(Collectors.toSet()));
推荐阅读
- ios - 如何从字符串中删除表情符号 - ios?
- android - 如何用 Dagger 注入 DialogFragment?
- ssis-2012 - 无效的 SQL 语句;预期 DELETE、INSERT、PROCEDURE、SELECT 或 UPDATE?
- javascript - 将 Cordova 版本 9.0.0 降级到 8.1.2 不起作用
- python - Py Spark No 这样的文件或目录问题
- c# - 无法将类型为“Newtonsoft.Json.Linq.JObject”的对象转换为类型“System.Collections.Generic.Dictionary`2[System.String,System.Object]”
- mysql - API 一次应该只返回 n 行
- flutter-layout - Flutter PageView 和 AudioPlayers
- mysql - 如何在 Docker 启动时自动选择 MySQL 数据库?
- grafana - Grafana - 使用 Prometheus(动态)属性/标签数据创建包含列值的表