我有两个Map
应该有相同的键(假设)。
我需要对相应的元素执行操作
Java 7代码:
Map<X,Y> m1, m2;
for (Map.Entry<X,Y> kvp: m1.entrySet()) {
K key = kvp.getKey();
Y value1 = kvp.getValue();
Y value2 = m2.get(key);
doSomething(value1, value2);
}
我的目标是使用lambda进行此类操作
像
这样的东西Map<X,Y> m1, m2;
[initStreamHere](m1, m2).forEachCorrespondingEntry((k, v1, v2)-> doSomething(v1, v2));
一般情况下,根据相应密钥的存在与否,如果v1
或v2
为空,则可能会很酷。
Java是否提供了这么酷的功能?或者是否可以使用少于50行的自定义代码实现?
我的目标是使用一个lambda表达式,它接受键和两个相应的值
答案 0 :(得分:1)
只要它只是一个奇怪的问题。对于制作/你的同事来说,写一些更容易理解的东西会更好。
interface EntryConsumer<K, V> {
void apply(K key, V v1, V v2);
}
public static <K, V> void fancyStreams(Map<K, V> m1, Map<K, V> m2, EntryConsumer<K, V> consumer) {
Stream
.concat(m1.entrySet().stream(), m2.entrySet().stream())
.filter(e -> e.getValue() != null) // filter out nulls
.collect(Collectors.groupingBy(Map.Entry::getKey))
.entrySet()
.stream()
.filter(e -> e.getValue().size() == 2) // filter out non-matching key-values
.forEach(e -> consumer.apply(e.getKey(), e.getValue().get(0).getValue(), e.getValue().get(1).getValue()));
}
public static <K, V> void plainOldIteration(Map<K, V> m1, Map<K, V> m2, EntryConsumer<K, V> consumer) {
m1.entrySet()
.forEach(e -> {
if (m2.containsKey(e.getKey()))
consumer.apply(e.getKey(), e.getValue(), m2.get(e.getKey()))
});
}
// Actual usage
Map<String, Integer> m1, m2;
m1 = Maps.of("1", 22, "2", 23);
m2 = Maps.of("1", 20, "2", 19, "3", 21);
fancyStreams(m1, m2, (k, v1, v2) -> System.out.println(k + ": " + (v1 + v2)));
plainOldIteration(m1, m2, (k, v1, v2) -> System.out.println(k + ": " + (v1 + v2)));
你的实际要求(稍微冗长一点)
public class EntryStream<K, V> {
private final Map<K, V> m1;
private final Map<K, V> m2;
private EntryStream(Map<K, V> m1, Map<K, V> m2) {
this.m1 = m1;
this.m2 = m2;
}
public static <K, V> EntryStream<K, V> of(Map<K, V> m1, Map<K, V> m2) {
return new EntryStream<>(m1, m2);
}
public void forEachCorrespondingEntry(EntryConsumer<K, V> consumer) {
m1.entrySet()
.forEach(e -> {
if (m2.containsKey(e.getKey())) consumer.apply(e.getKey(), e.getValue(), m2.get(e.getKey()));
});
}
}
// Usage
EntryStream.of(m1, m2).forEachCorrespondingEntry((k, v1, v2) -> System.out.println(k + ": " + (v1 + v2)));
答案 1 :(得分:0)
在这里,我写了一个很好的例子,说明如何为你的目的使用合并功能
public class MapCombine {
public static Map<String,Integer> combineMaps(Map<String,Integer>map1,Map<String,Integer>map2){
map2.forEach((key,value)->{
map1.merge( key, map1.get(key), MapCombine::combine);
});
return map1;
}
public static int combine(Integer a , Integer b) {
return a+b;
}
public static void main (String ...args) {
Map<String,Integer>map1 = new HashMap<>();
Map<String,Integer>map2 = new HashMap<>();
map1.put("Red", 1);
map1.put("Blue", 12);
map1.put("Black", 11);
map2.put("Red", 1);
map2.put("Blue", 111);
// This will print total for each color
System.out.println(combineMaps(map1, map2));
}
}
这是输出{Red = 2,Blue = 24,Black = 11}
答案 2 :(得分:-1)
这样的东西?
m1.entrySet()
.stream()
.filter(kvp -> m2.containsKey(kvp.getKey()))
.forEach(kvp -> doSomething(kvp.getValue(), m2.get(kvp.getKey())));