英文:
How to convert List of Map into Map of List using Java Streams
问题
我有一个List
,其中包含Map
,如下所示:
[{"a":"10","b":"20"},{"a":"12","b":"22"},{"a":"14","b":"24"}]
我想要一个Map
,如下所示:
{"a":["10","12","14"],"b":["20","22","24"]}
英文:
I have List
of Map
s as
[{"a"="10","b"="20"},{"a"="12","b"="22"},{"a"="14","b"="24"}]
And I want a Map
as
{"a"=["10","12","14"],"b"=["20","22","24"]}
答案1
得分: 7
你可以在不需要实例化额外数据结构的情况下完成这个任务。首先将Map
映射为Map.Entry
,然后按键分组。
var listOfMaps = List.of(
Map.of("a", 10, "b", 20),
Map.of("a", 12, "b", 22),
Map.of("a", 14, "b", 24)
);
var mapOfLists = listOfMaps.stream()
.map(Map::entrySet)
.flatMap(Set::stream)
.collect(Collectors.groupingBy(
Map.Entry::getKey,
Collectors.mapping(
Map.Entry::getValue,
Collectors.toList()
)
));
System.out.println(mapOfLists);
输出:
{a=[10, 12, 14], b=[20, 22, 24]}
英文:
You can do this without having to instantiate an additional data structure. You first map the Map
s to Map.Entry
and then group by key.
var listOfMaps = List.of(
Map.of("a", 10, "b", 20),
Map.of("a", 12, "b", 22),
Map.of("a", 14, "b", 24)
);
var mapOfLists = listOfMaps.stream()
.map(Map::entrySet)
.flatMap(Set::stream)
.collect(Collectors.groupingBy(
Map.Entry::getKey,
Collectors.mapping(
Map.Entry::getValue,
Collectors.toList()
)
));
System.out.println(mapOfLists);
Output:
{a=[10, 12, 14], b=[20, 22, 24]}
答案2
得分: 4
你可以使用Group By来实现这个目标。以下是一个示例。
首先,我们使用list.stream()
获取一个列表的流,然后使用flatMap
将每个Map的条目转换为流。现在我们有了每个条目(键-值对)的流,我们使用groupingBy
将它们收集为一组。
groupingBy
的第一个参数是用于派生键的函数,第二个参数是可选的,它是一个地图工厂,用于创建地图,如果您想要一个排序的地图,可以使用TreeMap::new
。现在第三个参数是reducer部分,您告诉它将被分组的值以及如何收集它们(在我们的情况下,我们希望它们成为一个列表)。
Map<String, String> ma = new java.util.HashMap<>();
ma.put("a", "10");
ma.put("b", "20");
Map<String, String> ma3 = new java.util.HashMap<>();
ma3.put("a", "15");
ma3.put("b", "17");
ma3.put("c", "19");
List<Map<String, String>> list = Arrays.asList(ma, ma3);
Map<String, List<String>> lm = list.stream()
.flatMap(x -> x.entrySet().stream())
.collect(Collectors.groupingBy(
Entry::getKey,
HashMap::new,
Collectors.mapping(Entry::getValue, Collectors.toList())
));
System.out.println(lm);
输出看起来像这样:
{a=[10, 15], b=[20, 17], c=[19]}
英文:
You can make use of Group By to achieve this. Here is an example.
First we take a stream of list using list.stream()
and then we make a stream of each Map's Entry using flatMap
. Now that we have a stream of each Entry(Key-value pair), we use groupingBy
to collect them as a group.
First argument of groupingBy
is functions what derive the key , Second argument is optional its a map factory which will be used to create the map, in case you want to have a sorted map you can use TreeMap::new
, Now third param is reducer part where you tell what will be the grouped value and how it has to be collected(in our case we want it into a list)
Map<String, String> ma = new java.util.HashMap<>();
ma.put("a", "10");
ma.put("b", "20");
Map<String, String> ma3 = new java.util.HashMap<>();
ma3.put("a", "15");
ma3.put("b", "17");
ma3.put("c", "19");
List<Map<String, String>> list = Arrays.asList(ma, ma3);
Map<String, List<String>> lm = list.stream().flatMap(x -> x.entrySet().stream()).collect(Collectors
.groupingBy(Entry::getKey, HashMap::new, Collectors.mapping(Entry::getValue, Collectors.toList())));
System.out.println(lm);
Output looks like
{a=[10, 15], b=[20, 17], c=[19]}
答案3
得分: 3
Map<String, List<String>> map = new HashMap<>();
list.stream().flatMap(map -> map.entrySet().stream()).forEach(entry -> {
map.putIfAbsent(entry.getKey(), new ArrayList<>());
map.get(entry.getKey()).add(entry.getValue());
});
这段代码的目的是将一个包含多个内部Map
的List
转换为一个包含相同键的Map
,其中每个键关联一个值列表。
它不是一个单行代码,因为在forEach
中需要两个语句,我不喜欢将这样的代码写成一行,但是提问者没有要求一行代码。
代码首先将内部Map
的所有条目作为Stream
获取(使用flatMap
)。
然后,它对这些条目进行迭代,执行两个操作:
- 如果条目值的
List
不存在,则添加一个新的空列表。 - 将条目的值添加到条目的内部列表中。
英文:
Map<String,List<String>> map=new HashMap<>();
list.stream().flatMap(map->map.entrySet().stream()).forEach(entry->{
map.putIfAbsent(entry.getKey(),new ArrayList<>());
map.get(entry.getKey()).add(entry.getValue());
});
It is not a one-liner because I needed two statements in the forEach
and I don't like to put something like that in one line but the OP did not ask for a one-liner.
It gets all entries of the inner Map
as a Stream
at first (flatMap
).
After that, it iterates over them doing two actions:
-
If no
List
exists for the entry value, a new one is added. -
The value of the entry is added to the inner list of the entry.
答案4
得分: 2
你可以在 Map#merge
中使用重新映射功能。
final Map<String, List<String>> result = new HashMap<>();
maps.forEach(map -> map.entrySet().forEach(entry ->
result.merge(entry.getKey(), Arrays.asList(entry.getValue()),
(a, b) -> Stream.concat(a.stream(), b.stream()).collect(Collectors.toList()))));
英文:
You can make use of the remapping function in Map#merge
.
final Map<String,List<String>> result = new HashMap<>();
maps.forEach(map -> map.entrySet().forEach(entry ->
result.merge(entry.getKey(), Arrays.asList(entry.getValue()),
(a,b)->Stream.concat(a.stream(),b.stream()).collect(Collectors.toList()))));
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论