java 8 将具有相同键和值的映射分组并组成键值对

java 8 grouping a map of same key and value and make a key value pair

我有一个方法 fetchConfigsCount() returns List<Map<String, Object>>

结果如下:

{
    "web_id": "abc",
    "count": 1
},
{
    "web_id": "xyz",
    "count": 1
},
{
    "web_id": "pqr",
    "count": 1
}

我们有另一种方法 fetchWebsitesCount(),它也 returns 一个相同格式的响应。

web_id 是键,其值为所有者名称。 count 是另一个键,它的值是 int.

类型
{
    "web_id": "abc",
    "count": 2
},
{
    "web_id": "xyz",
    "count": 3
},
{
    "web_id": "pqr",
    "count": 4
}

我们有一个类型为 ArrayList<String>:

的所有者列表
List<String> listOfOwners = ["abc","xyz","pqr"];

我想收集所有这些东西并想创建如下结果:

result:[
    {"owner": "abc",
    "ownerPresence":{
    "configCount":1,
    "websiteCount":2
    },
    {"owner": "xyz",
    "ownerPresence":{
    "configCount":1,
    "websiteCount":3
    },
    {"owner": "pqr",
    "ownerPresence":{
    "configCount":1,
    "websiteCount":4
    }]

我不确定如何在 Java 8 中做到这一点。

  1. 将初始地图列表重新映射到 Map<String, Integer>:
static Map<String, Integer> convert(List<Map<String, Object>> list) {
    return list
        .stream()
        .collect(Collectors.toMap(
            m -> (String) m.get("web_id"),
            m -> (Integer) m.get("count")
        ));
}

List<Map<String, Object>> configs  = fetchConfigsCount();
List<Map<String, Object>> websites = fetchWebsitesCount();

Map<String, Integer> configMap  = convert(configs);
Map<String, Integer> websiteMap = convert(websites);
  1. 创建一个 POJO 来表示列表条目:
class Pojo {
    String owner;
    Map<String, Integer> ownerPresence;
    // boilerplate: constructor(s), getters/setters
}
  1. 流式传输所有者列表,并构建地图:
List<String> listOfOwners = Arrays.asList("abc","xyz","pqr");

List<Pojo> result = listOfOwners
    .stream()
    .map(owner -> new Pojo(
        owner,
        Map.of(
            "configCount",  configMap.get(owner),
            "websiteCount", websiteMap.get(owner)
        )
    ))
    .collect(Collectors.toList());

更新

如果有其他输入,可以创建包装器映射以通过适当的键 "configCount", "websiteCount", "sourceCount" 等保存转换后的映射:

Map<String, Map<String, Integer>> bigMap = Map.of(
    "configCount",  convert(fetchConfigsCount()),
    "websiteCount", convert(fetchWebsitesCount()),
    "sourceCount",  convert(fetchSourcesCount())
);

然后 Pojo 的地图可以这样创建:

List<Pojo> result = listOfOwners
    .stream()
    .map(owner -> new Pojo(
        owner,
        bigMap.keySet()
            .stream() // Stream<String>
            .collect(Collectors.toMap(
                k -> k,
                k -> bigMap.get(k).get(owner)
            )) // Map<String, Integer>
    ))
    .collect(Collectors.toList());

这是一种方法。

  • 首先,只需将计数重新映射到 Map<String,List<Integer>>
  • 然后简单地迭代 map,构建最终的 map 和列表。
List<Map<String, Object>> configCount =
        List.of(Map.of("web_id", "abc", "count", 1),
                Map.of("web_id", "xyz", "count", 1),
                Map.of("web_id", "pqr", "count", 1));

List<Map<String, Object>> webCount =
        List.of(Map.of("web_id", "abc", "count", 2),
                Map.of("web_id", "xyz", "count", 3),
                Map.of("web_id", "pqr", "count", 4));

List<Map<String, Object>> sourceCount =
        List.of(Map.of("web_id", "abc", "count", 22),
                Map.of("web_id", "xyz", "count", 32),
                Map.of("web_id", "pqr", "count", 42));

Map<String, List<Integer>> map = Stream
                .concat(configCount.stream(),
                        Stream.concat(webCount.stream(),
                                sourceCount.stream()))
        .collect(Collectors.groupingBy(
                mp -> (String) mp.get("web_id"),
                Collectors.mapping(
                        mp -> (Integer) mp.get("count"),
                        Collectors.toList())));

上面创建了以下内容,其中第一个 List 值按顺序为“配置、网站和来源”。

pqr=[1, 4, 42]
abc=[1, 2, 22]
xyz=[1, 3, 32]

现在实例化一个最终列表来保存所有地图并完成。

List<Map<String, Object>> result = new ArrayList<>();

for (Entry<String, List<Integer>> e : map.entrySet()) {
    Map<String, Object> tempMap = new HashMap<>();
    tempMap.put("owner", e.getKey());
    tempMap.put("ownerPresence",
            new HashMap<>(Map.of("configCount",e.getValue().get(0),
                                "webSiteCount",e.getValue().get(1),
                                "sourceCount", e.getValue().get(2))));
    result.add(tempMap);
}

result.forEach(mp -> mp.entrySet()
          .forEach(e -> System.out.println(e.getKey() + ":" + e.getValue())));

打印

owner:pqr
ownerPresence:{sourceCount=42, webSiteCount=4, configCount=1}
owner:abc
ownerPresence:{sourceCount=22, webSiteCount=2, configCount=1}
owner:xyz
ownerPresence:{sourceCount=32, webSiteCount=3, configCount=1}