java8对相同键值的映射进行分组,形成键值对



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

结果看起来像:

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

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

web_id是密钥,其值是所有者名称。CCD_ 5是另一个密钥,并且其值的类型为CCD_。

{
"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
}]

我不知道如何在Java8中做到这一点。

这里有一种方法。

  • 首先,只需将计数重新映射到Map<String,List<Integer>>
  • 然后简单地对than 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值依次为"config、website和source"。

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

现在实例化一个最终的List来保存所有的映射并完成。

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}
  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());

最新更新