我有一个情况,我Player
在开发项目中有对象,任务只是测量距离并返回低于某个阈值的结果.当然,我想以最简洁的方式使用流.
目前,我有一个映射流的解决方案,然后通过迭代器过滤:
Streamstr = /* source of my player stream I'm filtering */; Map dists = str.collect(Collectors.toMap(...)); //mapping function Iterator > itr = map.entrySet().iterator(); while (itr.hasNext()) { if (itr.next().getValue() <= radiusSquared) { itr.remove(); } }
但是,我想要实现的是在对流进行操作时执行此过滤的内容,即"如果此谓词失败,不收集",则尝试并保存第二次迭代.另外,我不想计算两次距离,所以通过映射函数进行过滤,然后重新映射不是一个合理的解决方案.
我想到的唯一真正可行的解决方案是映射到a Pair
,但如果有某种形式的二进制流的原生支持,那就更好了.
java的流API中是否有本机支持?
Map
之后过滤并不像看起来那么糟糕,请记住,迭代a Map
并不意味着执行查找(例如散列)的成本相同.
而不是
Iterator> itr = map.entrySet().iterator(); while (itr.hasNext()) { if (itr.next().getValue() <= radiusSquared) { itr.remove(); } }
你可以简单地使用
map.values().removeIf(value -> value <= radiusSquared);
即使您坚持将其作为collect
操作的一部分,您也可以将其作为后缀操作:
Mapdists = str.collect( Collectors.collectingAndThen(Collectors.toMap(p->p, p->calculate(p)), map -> { map.values().removeIf(value -> value <= radiusSquared); return map; }));
可以首先避免put
不需要的条目,但它意味着手动回溯现有toMap
收集器的作用:
Mapdists = str.collect( HashMap::new, (m, p) -> { double value=calculate(p); if(value > radiusSquared) m.put(p, value); }, Map::putAll);