我有一些Map
个对象,这些对象由具有不同类型值K
的相同类型V1...VN
键入,为了此问题的目的,不共享超类型*:< / p>
Map<K, V1> kv1
Map<K, V2> kv2
Map<K, V3> kv3
...
Map<K, VN> kvN
我需要创建一个Map<K, V>
类型的结果地图,通过不同地过滤每个地图,然后使用&#39;值映射器&#39;在这些地图上将V1...VN
值映射到常用类型V
新值(即Function<? super Entry<K, VN>, ? extends V>
)。因此,我有以下static
辅助方法来执行前两个步骤:
public static <K, VN, V> Map<K, V> filterAndMapValue(final Map<K, VN> map,
final Predicate<? super Entry<K, VN>> predicate,
final Function<? super Entry<K, VN>, ? extends V> mapper) {
return map.entrySet().stream().filter(predicate)
.collect(Collectors.toMap(Entry::getKey, mapper));
}
我当前的用例可以安全地假设只有在每个地图上的过滤后才能为我提供最终Map
对象的不同密钥(可以使用相同的密钥)每个地图),但如果将来不成立,我知道我可以向mergeFunction
提供补充Collectors.toMap(Function, Function, BinaryOperator)
表达式来正确处理。
最终代码现在读取如下内容:
Map<K,V> result = filterAndMapValue(kv1, predicateForKV1, mapV1toV);
result.putAll(filterAndMapValue(kv2, predicateForKV2, mapV2toV));
result.putAll(filterAndMapValue(kv2, predicateForKV3, mapV3toV));
...
result.putAll(filterAndMapValue(kvN, predicateForKVN, mapVNtoV));
// do something with result
问题:有更有效的方法吗?这听起来像是另一种将东西(过滤后的地图)减少到最终集合(Map
)的情况,它需要不同的减少调用(值映射部分),我不确定我是否正在以正确的方式接近或不
* - 如果他们这样做,那么我猜V1...VN
可以实现一个父方法,比如V convertToV(Object... possiblyAdditionalArgumentsToPerformTheConversion)
,这样我的问题就减少到只为不同的地图应用不同形式的过滤。如果还有一个更简单的解决方案给出了这个替代假设,也可以随意提及。
答案 0 :(得分:2)
如果您将方法更改为
public static <K, VN, V> Stream<Entry<K, V>> filterAndMapValue(Map<K, VN> map,
Predicate<? super Entry<K, VN>> predicate,
Function<? super Entry<K, VN>, ? extends V> mapper) {
return map.entrySet().stream().filter(predicate)
.map(e->new AbstractMap.SimpleEntry<>(e.getKey(), mapper.apply(e)));
}
您可以将操作作为单个Stream
操作执行,如:
Stream.of(filterAndMapValue(kv1, predicateForKV1, mapV1toV),
filterAndMapValue(kv2, predicateForKV2, mapV2toV),
filterAndMapValue(kv3, predicateForKV3, mapV3toV),
…)
.flatMap(Function.identity())
.collect(Collectors.toMap(Entry::getKey, Entry::getValue));
请注意,对于少量输入地图,您可以使用Stream.concat
但随着数字的增长,上面显示的方法更可取。
我不希望显着的性能提升,但这种方法将验证您的假设,其余条目中没有重复的密钥。