根据地图的唯一键将地图条目列表分组为单个条目

时间:2018-10-18 21:44:51

标签: java list lambda java-8

我有一个地图列表List<Map>,其中不同的列表条目可能具有相同的 ID 值。我需要将两个列表项合并到具有相同键值和其他值分组在一起的单个列表记录中。例如,

List<HashMap> data= new ArrayList<>();

Map<String, List<String>> map1= new HashMap<>();
Map<String, List<String>> map2= new HashMap<>();
Map<String, List<String>> map3= new HashMap<>();

map1.put("ID","100");
map1.put("Dept",Arrays.asList("Accounting,"Finance"));
map1.put("Employees",Arrays.asList("100","350"));

map2.put("ID","200");
map2.put("Dept",Arrays.asList("IT","Technology"));
map2.put("Employees",Arrays.asList("300",400"));

map3.put("ID","100");
map3.put("Dept",Arrays.asList("Health","Medical"));
map3.put("Employees",Arrays.asList("450","550"));

data.add(map1);
data.add(map2);
data.add(map3);

我的输入列表将是以下输出:

List data = [
    [ID: "100", Dept: ["Accounting","Finance"], Employees: ["100","350"]],
    [ID: "200", Dept: ["IT","Technology"], Employees: ["300","400"]],
    [ID: "100", Dept: ["Health","Medical"], Employees: ["450","550"]]   
]

我的预期输出应该是:

List data = [
    [ID: "100", Dept: ["Accounting","Finance","Health","Medical"], Employees: "100","350",450","550"],
    [ID: "200", Dept: ["IT","Technology"], Employees: ["300","400"]]   
]

我可以使用迭代器并循环检查列表条目是否在映射中包含相同的id值,但是有没有更好的方法使用java8中的函数编程来做到这一点?

谢谢

1 个答案:

答案 0 :(得分:0)

这是您想要的解决方案:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.stream.Collectors;

public class MergeMap{

  public static final String DEPT = "Dept";
  public static final String EMPLOYEES = "Employees";
  public static final String ID = "ID";

  public static void main(String[] args) {
    List<Map<String, List<String>>> data = new ArrayList<>();

    Map<String, List<String>> map1 = new ConcurrentHashMap<>();
    Map<String, List<String>> map2 = new ConcurrentHashMap<>();
    Map<String, List<String>> map3 = new ConcurrentHashMap<>();

    map1.put(ID, Arrays.asList("100"));
    map1.put(DEPT, Arrays.asList("Accounting", "Finance"));
    map1.put(EMPLOYEES, Arrays.asList("100", "350"));

    map2.put(ID, Arrays.asList("200"));
    map2.put(DEPT, Arrays.asList("IT", "Technology"));
    map2.put(EMPLOYEES, Arrays.asList("300", "400"));

    map3.put(ID, Arrays.asList("100"));
    map3.put(DEPT, Arrays.asList("Health", "Medical"));
    map3.put(EMPLOYEES, Arrays.asList("450", "550"));

    data.add(map1);
    data.add(map2);
    data.add(map3);
    System.out.println(data);//previous list

    List<Map> expectedList = data
        .stream()
        .collect(
            Collectors.collectingAndThen(Collectors.toMap(e -> e.get(ID), Function.identity(),
                (left, right) -> {
                  List<String> dept = new ArrayList<>();
                  List<String> emp = new ArrayList<>();
                  dept.addAll(left.get(DEPT));
                  dept.addAll(right.get(DEPT));
                  emp.addAll(left.get(EMPLOYEES));
                  emp.addAll(right.get(EMPLOYEES));
                  left.put(DEPT, dept);
                  left.put(EMPLOYEES, emp);
                  return left;
                }
            ), m -> new ArrayList<>(m.values())));
    System.out.println(expectedList); // new list

  }

}

这是输出: 合并之前:

[{Dept=[Accounting, Finance], Employees=[100, 350], ID=[100]}, {Dept=[IT, Technology], Employees=[300, 400], ID=[200]}, {Dept=[Health, Medical], Employees=[450, 550], ID=[100]}]

合并后:

[{Dept=[Accounting, Finance, Health, Medical], Employees=[100, 350, 450, 550], ID=[100]}, {Dept=[IT, Technology], Employees=[300, 400], ID=[200]}]