Search code examples
javadictionarymergecollectionsjava-stream

Merge list of maps with duplicate keys


I have a list of HashMap<Integer, ArrayList<String>> and would like to merge them in a loop. The problem is that each map's key starts from 0 so the keys will be duplicated. The putAll() does not work as it overrides the keys and always gives me the last map.

I have seen examples of merging two maps by using Stream but in my case, there might be more than 2 maps. I am trying to generate a merged map that has an incremental key. For example:

Let's say I have 2 maps in the list (could be more) and both keys start from 0 but ends at different values.

1st map, the key starts at 0 ends at 10

2nd map, the key starts at 0 ends at 15

Is it possible to add the second map with the key starting at 11? In the end, I need a merged map in which the first key starts at 0 and the last key ends at 25.


Solution

  • Assuming you have a list of maps, where the keys of each map are integers in range [0-k], [0-n], [0, r] ... and your resulting map should a key set in the range of [0 - (k+n+r..)] something like below should work:

    public static void main(String[] args) throws IOException {
       //example list of maps
       List<Map<Integer,List<String>>> mapList = List.of(
               Map.of( 0,List.of("foo","foo"), 
                       1,List.of("bar","bar"), 
                       2,List.of("baz","baz")),
               Map.of( 0,List.of("doo","doo"), 
                       1,List.of("gee","gee"), 
                       2,List.of("woo","woo")),
               Map.of( 0,List.of("cab","cab"), 
                       1,List.of("kii","kii"), 
                       2,List.of("taa","taa"))
       );
       AtomicInteger ai = new AtomicInteger();
       Map<Integer,List<String>> result = 
               mapList.stream()
                       .flatMap(map -> map.values().stream())
                       .collect(Collectors.toMap(list -> ai.getAndIncrement(), Function.identity()));
       result.forEach((k,v) ->{
           System.out.println(k + " : " + v);
       });
    }