Java 8流来收集项目列表的Map

use*_*342 3 java java-8 java-stream

我有一张地图列表,用于存储角色和人名.例如:

List<Map<String, String>> listOfData

1) Role:  Batsman
   Name:  Player1

2)Role:  Batsman
   Name:  Player2

3)Role:  Bowler
   Name:  Player3
Run Code Online (Sandbox Code Playgroud)

角色和名称是地图的键.我想将其转换为a Map<String, List<String>> result,这将为我提供每个角色的名称列表,即

k1: Batsman  v1: [Player1, Player2]
k2: Bowler   v2: [Player3]


listOfData
    .stream()
    .map(entry -> new AbstractMap.SimpleEntry<>(entry.get("Role"), entry.get("Name"))
    .collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)

这样做不会给我一个角色名称列表,它会给我一个名字.如何继续收集列表的元素,然后将其添加到密钥?

用于创建基础结构的Java代码:

Map<String, String> x1 = ImmutableMap.of("Role", "Batsman", "Name", "Player1");

        Map<String, String> y1 = ImmutableMap.of("Role", "Batsman", "Name", "Player2");

        Map<String, String> z1 = ImmutableMap.of("Role", "Bowler", "Name", "Player3");


        List<Map<String, String>> list = ImmutableList.of(x1, y1, z1);
        Map<String, List<String>> z = list.stream()
                    .flatMap(e -> e.entrySet().stream())
                    .collect(Collectors.groupingBy(Map.Entry::getKey,
                            Collectors.mapping(Map.Entry::getValue, Collectors.toList())));
Run Code Online (Sandbox Code Playgroud)

小智 15

Collectors类以groupingBy的形式提供了方便的方法,它允许通过某个分类器对相似的对象进行分组分类器方法是该特定分组函数的输入。该函数将生成一个 Map,以相应的分类器方法值作为键,并以共享相同分类器方法值作为值的对象列表。

因此像这样的代码

Map<String, List<Person>> roles2Persons = 
    lis.stream().collect(Collectors.groupingBy(Person::getRole));
Run Code Online (Sandbox Code Playgroud)

将为对象可能满足的各个角色生成映射到与映射中的键共享相同角色Person的对象列表。Person

应用上述收集器后,生成的地图将包含所需的形式

key1: Batsman, values: List(Player1, Player2)
key2: Bowler, values: List(Player3)
Run Code Online (Sandbox Code Playgroud)

  • 虽然此代码可以回答问题,但提供有关此代码为何和/或如何回答问题的附加上下文可以提高其长期价值。 (4认同)

use*_*342 9

基于 Aomine 给出的想法:

list.stream()
    .map(e -> new AbstractMap.SimpleEntry<>(e.get("Role"), e.get("Name")))
    .collect(Collectors.groupingBy(Map.Entry::getKey,
                    Collectors.mapping(Map.Entry::getValue, Collectors.toList())));
Run Code Online (Sandbox Code Playgroud)


Ous*_* D. 5

listOfData.stream()
          .flatMap(e -> e.entrySet().stream())
          .collect(Collectors.groupingBy(Map.Entry::getKey, 
                         Collectors.mapping(Map.Entry::getValue, 
                                    Collectors.toList())));
Run Code Online (Sandbox Code Playgroud)

更新:

与完整性user1692342答案略有不同.

list.stream()
    .map(e -> Arrays.asList(e.get("Role"), e.get("Name")))
    .collect(Collectors.groupingBy(e -> e.get(0),
             Collectors.mapping(e -> e.get(1), Collectors.toList())));
Run Code Online (Sandbox Code Playgroud)