[英]Merging Map streams using Java 8 Lambda Expression
我有两个Map<Integer, String>
类型的映射m1
和m2
,它们必须合并到一个映射Map<Integer, List<String>>
,其中两个映射中相同键的值被收集到一个 List 和放入新地图。
基于我探索的解决方案:
Map<Integer, List<String>> collated =
Stream.concat(m1.entrySet().stream(), m2.entrySet().stream()).collect(
Collectors.toMap(Entry::getKey,
Entry::getValue, (a, b) -> {
List<String> merged = new ArrayList<String>(a);
merged.addAll(b);
return merged;
}));
但是,这个解决方案期望源List
是Map<Integer, List<String>>
因为 toMap 中的合并函数期望操作数和结果是相同的类型。
我不想更改源集合。 请提供有关使用 lambda 表达式实现此目标的输入。
这是groupingBy
收集器的工作:
Stream.of(m1,m2)
.flatMap(m->m.entrySet().stream())
.collect(groupingBy(
Map.Entry::getKey,
mapping(Map.Entry::getValue, toList())
));
我现在不能测试它,但我认为你需要它来将值的映射从Entry::getValue
更改为包含该值的 List :
Map<Integer, List<String>> collated =
Stream.concat(m1.entrySet().stream(), m2.entrySet().stream())
.collect(Collectors.toMap(Entry::getKey,
e -> {
List<String> v = new ArrayList<String>();
v.add(e.getValue());
return v;
},
(a, b) -> {
List<String> merged = new ArrayList<String>(a);
merged.addAll(b);
return merged;
}));
编辑:这个想法是正确的。 语法不是。 当前语法有效,虽然有点难看。 必须有一种更短的方式来编写它。
您还可以将e -> {..}
替换为e -> new ArrayList<String>(Arrays.asList(new String[]{e.getValue()}))
。
或使用e -> Stream.of(e.getValue()).collect(Collectors.toList())
或者你可以用groupingBy
来做到:
Map<Integer, List<String>> collated =
Stream.concat(m1.entrySet().stream(), m2.entrySet().stream())
.collect(Collectors.groupingBy(Map.Entry::getKey,
Collectors.mapping(Map.Entry::getValue,
Collectors.toList())));
这似乎是使用 Guava 的Multimap
的绝佳机会。
ListMultimap<Integer, String> collated = ArrayListMultimap.create();
collated.putAll(Multimaps.forMap(m1));
collated.putAll(Multimaps.forMap(m2));
如果你真的需要一个Map<Integer, List<String>>
:
Map<Integer, List<String>> mapCollated = Multimaps.asMap(collated);
为清楚起见,您可以使用带有三个参数的Collectors.toMap
方法。
Map<Integer, String> m1 = Map.of(1, "A", 2, "B");
Map<Integer, String> m2 = Map.of(1, "C", 2, "D");
// two maps into one
Map<Integer, List<String>> m3 = Stream
.of(m1.entrySet(), m2.entrySet())
.flatMap(Collection::stream)
.collect(Collectors.toMap(
// key - Integer
e -> e.getKey(),
// value - List<String>
e -> List.of(e.getValue()),
// mergeFunction - two lists into one
(list1, list2) -> {
List<String> list = new ArrayList<>();
list.addAll(list1);
list.addAll(list2);
return list;
}));
// output
System.out.println(m3); // {1=[A, C], 2=[B, D]}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.