Convert List of Maps to single Map via streams

后端 未结 4 1244
时光取名叫无心
时光取名叫无心 2020-12-06 03:00

I query the DB for two columns where the first one is the key to the second one. How can I convert the resulting list to a single map? Is it even possible? I have just seen

相关标签:
4条回答
  • 2020-12-06 03:24

    You forgot to convert your key and value mappings to produce String:

    final Map<String, String> result = steps
                    .stream()
                    .collect(Collectors.toMap(s -> (String) s.get("key"), s -> (String) s.get("value")));
    

    Full example

    public static void main(String[] args) {
        final List<Map<String, Object>> steps = queryForList("SELECT key, value FROM table");
        final Map<String, String> result = steps
                .stream()
                .collect(Collectors.toMap(s -> (String) s.get("key"), s -> (String) s.get("value")));
        result.entrySet().forEach(e -> System.out.println(e.getKey() + " -> " + e.getValue()));
    }
    
    private static List<Map<String, Object>> queryForList(String s) {
        final List<Map<String, Object>> result = new ArrayList<>();
    
        for (int i = 0; i < 10; i++) {
            final Map<String, Object> map = new HashMap<>();
            map.put("key", "key" + i);
            map.put("value", "value" + i);
            result.add(map);
        }
    
        return result;
    }
    

    Which prints

    key1 -> value1
    key2 -> value2
    key0 -> value0
    key5 -> value5
    key6 -> value6
    key3 -> value3
    key4 -> value4
    key9 -> value9
    key7 -> value7
    key8 -> value8
    
    0 讨论(0)
  • 2020-12-06 03:24

    The problem is you have a list of maps. The code below should work:

    Map<String, String> result = new HashMap<>();
    steps.stream().forEach(map -> {
        result.putAll(map.entrySet().stream()
            .collect(Collectors.toMap(entry -> entry.getKey(), entry -> (String) entry.getValue())));
    });
    

    If we try to run this example

    Map<String, Object> steps1 = new HashMap<>();
    steps1.put("key11", "value11");
    steps1.put("key12", "value12");
    
    Map<String, Object> steps2 = new HashMap<>();
    steps2.put("key21", "value21");
    steps2.put("key22", "value22");
    
    List<Map<String, Object>> steps = new ArrayList<>();
    steps.add(steps1);
    steps.add(steps2);
    
    Map<String, String> result = new HashMap<>();
    steps.stream().forEach(map -> {
        result.putAll(map.entrySet().stream()
            .collect(Collectors.toMap(entry -> entry.getKey(), entry -> (String) entry.getValue())));
    });
    System.out.println(result);
    

    It happily gives us the output like that:

    {key12=value12, key11=value11, key22=value22, key21=value21}
    
    0 讨论(0)
  • 2020-12-06 03:31

    We can use the reduce() of java streams to convert a list of maps to a single map in java.

    Please check the following code on how it is used.

    For example:

    @Data
    @AllArgsConstructor
    public class Employee {
    
        private String employeeId;
        private String employeeName;
        private Map<String,Object> employeeMap;
    }
    
    
    public class Test{
     public static void main(String[] args) {
     
            Map<String, Object> map1 = new HashMap<>();
            Map<String, Object> map2 = new HashMap<>();
            Map<String, Object> map3 = new HashMap<>();
            
            
            map1.put("salary", 1000);
            Employee e1 = new Employee("e1", "employee1", map1);
    
            map2.put("department", "HR");
            Employee e2 = new Employee("e2", "employee2", map2);
    
            map3.put("leave balance", 14);
            Employee e3 = new Employee("e3", "employee3", map3);
            
            //now we create a employees list and add the employees e1,e2 and e3.
            List<Employee> employeeList = Arrays.asList(e1,e2,e3);
             
            //now we retreive employeeMap from all employee objects and therefore have a List of employee maps.
            List<Map<String, Object>> employeeMaps = employeeList
            .stream()
            .map(Employee::getEmployeeMap)
            .collect(Collectors.toList());
    
            System.out.println("List of employee maps: " + employeeMaps);
            
            // to reduce a list of maps to a single map, we use the reduce function of stream.
            
            Map<String, Object> finalMap = employeeMaps
            .stream()
            .reduce((firstMap, secondMap) -> {
                    firstMap.putAll(secondMap);
                     return firstMap;
                  }).orElse(null);
                   
            System.out.println("final Map: "+ finalMap);             
            
    }
    }
    

    Output: List of employee maps: [{salary=1000}, {department=HR}, {leave balance=14}].

    final Map: {salary=1000, department=HR, leave balance=14}

    PS: Apologies for the extended answer, this is my first time in stackoverflow. Thank you :-)

    0 讨论(0)
  • 2020-12-06 03:36

    Adding on to what esin88 said above, if there is a possibility that we get duplicate keys in the list of maps, we would like to get a map with key and list of values rather than key value pair which can be done like below.

        public static void main(String[] args) {
        final List<Map<String, Object>> steps = queryForList("SELECT key, value FROM table");
        /*final Map<String, String> result = steps.stream()
                .collect(Collectors.toMap(s -> (String) s.get("key"), s -> (String) s.get("value")));*/
        final Map<String, List<String>> result1 = steps.stream()
                .collect(Collectors.groupingBy(k -> String.valueOf(k.get("key")),
                        Collectors.mapping(l -> String.valueOf(l.get("value")), Collectors.toList())));
        result1.entrySet().forEach(e -> System.out.println(e.getKey() + " -> " + e.getValue()));
    }
    
    private static List<Map<String, Object>> queryForList(String s) {
        final List<Map<String, Object>> result = new ArrayList<>();
        Map<String, Object> map = new HashMap<>();
        for (int i = 0; i < 10; i++) {
            map = new HashMap<>();
            map.put("key", "key" + i);
            map.put("value", "value" + i);
            result.add(map);
        }
        map = new HashMap<>();
        map.put("key", "key1");
        map.put("value", "value20");
        result.add(map);
    
        return result;
    }
    

    The result would look like

    key1 -> [value1, value20]
    key2 -> [value2]
    key0 -> [value0]
    key5 -> [value5]
    key6 -> [value6]
    key3 -> [value3]
    key4 -> [value4]
    key9 -> [value9]
    key7 -> [value7]
    key8 -> [value8]
    
    0 讨论(0)
提交回复
热议问题