java - 如何在添加到地图之前从收集器中的方法调用中过滤数据
问题描述
我有结构
interface Foo{
List<Bar> getBars();
}
interface Bar{
List<Number> getValues();
}
并列出List<Foo> foos
我想要的是创建看起来或多或少像这样的地图,其中不包括 foo 没有 bar 或 bar 没有值的条目。
{
fooid :{
barId : bar
}
}
显然我的第一个想法是做
foos.stream().filter(f->!f.getBars().isEmpty())
.collect( Collectors.toMap(
f->f.id(),
f->f.getBars().stream().filter(b->!b.getValues().isEmpty())
.collect(Collectors.toMap( b->b.id(),b->b.getValues()
))));
问题是我调用getValues
了两次方法,这是一种昂贵的方法,处理这样的调用的最佳做法是什么?
解决方案
我想这就是你要找的:
private static void doMap(List<Foo> foos) {
foos.stream()
.filter(foo -> !foo.getBars()
.isEmpty())
.map(foo -> new SimpleEntry<>(foo.getId(), foo.getBars()
.stream()
.map(bar -> new SimpleEntry<>(bar.getId(), bar.getValues()))
.filter(entry -> !entry.getValue()
.isEmpty())
.collect(entriesToMapCollector())))
.filter(entry -> !entry.getValue().isEmpty())
.collect(entriesToMapCollector());
}
private static <K, V> Collector<Entry<K, V>, ?, Map<K, V>> entriesToMapCollector() {
return Collectors.toMap(Entry::getKey, Entry::getValue);
}
(为了可读性、可维护性和一切能力,我强烈主张对此采取更命令式的方法——请不要在生产代码中这样做)
推荐阅读
- c - 当输入多于所需的输入时,sscanf 检查不起作用
- sql - Laravel 7 查询关系表
- anzograph - Anzograph - 如何为 5600 配置不同的端口
- javascript - 如何用最新的 Babel + Gulp 替换 @babel/polyfill?
- docker - 如何通过文件名从 docker linux 容器下载文件到客户端文件系统?
- python - Selenium find_elements_by_class_name 未返回完整列表
- r - data.table:以列为输入对大型 data.table 执行高效的逐行操作
- javascript - 如何使用 Ajax 进行 PATCH - REST API
- sql - SQL:与来自另一个表的匹配祖先连接(内部连接)
- javascript - Discord.js 机器人嵌入消息未显示机器人头像