Home > front end >  How to merge 3 map of maps effectively in java
How to merge 3 map of maps effectively in java

Time:02-22

Merge below 3 maps if values exist then replace and if the value is new then add that value, for example :-

I have a Map1 as :-

{
     BMW = {
        SIZE=1, 
        SPEED=60
    }, 
     AUDI = {
        SIZE=5, 
        SPEED=21
    },
     SEAT= {
        SPEED=15
     }
}

And a Map2 as :-

{
         Suzuki = {
            WHEELS_SIZE=2, 
            DOORS=3
        }, 
         AUDI = {
            WHEELS_SIZE=5,
            SIZE=4,
            DOORS=5
        },
         SEAT= {
            DOORS=4
         }
    }

And Map3 as :-

{
         
         TOYOTA = {
            WHEELS_SIZE=5, 
            DOORS=5
        },
         BMW= {
            SIZE=10
         }
    }

I have a requirement to merge all 3 above so, that final map looks like

{
         BMW = {
            SIZE=10, 
            SPEED=60
        }, 
         AUDI = {
            SIZE=4, 
            SPEED=21,
            WHEELS_SIZE=5, 
            DOORS=5
        },
         SEAT= {
            SPEED=15,
            DOORS=4
         },
         Suzuki = {
            WHEELS_SIZE=2, 
            DOORS=3
        },
        TOYOTA = {
            WHEELS_SIZE=5, 
            DOORS=5
        },
    }

Could someone please suggest an optimized way to achieve this ? Thanks in advance!

CodePudding user response:

Here is a naïve implementation:

public static void main(String[] args){
        Map<String, Integer> BMW1 = new HashMap<>();
        BMW1.put("SIZE", 1);
        BMW1.put("SPEED", 60);
        Map<String, Integer> AUDI1 = new HashMap<>();
        AUDI1.put("SIZE", 5);
        AUDI1.put("SPEED", 21);
        Map<String, Integer> SEAT1 = new HashMap<>();
        SEAT1.put("SPEED", 15);
        Map<String, Map<String, Integer>> one =
                Map.of("BMW", BMW1, "AUDI", AUDI1, "SEAT", SEAT1);

        Map<String, Integer> SUZUKI2 = new HashMap<>();
        SUZUKI2.put("WHEEL_SIZE", 2);
        SUZUKI2.put("DOORS", 3);
        Map<String, Integer> AUDI2 = new HashMap<>();
        AUDI2.put("WHEELS_SIZE", 5);
        AUDI2.put("SIZE", 4);
        AUDI2.put("DOORS", 5);
        Map<String, Integer> SEAT2 = new HashMap<>();
        SEAT2.put("DOORS", 4);
        Map<String, Map<String, Integer>> two =
                Map.of("SUZUKI", SUZUKI2, "AUDI", AUDI2, "SEAT", SEAT2);

        Map<String, Integer> TOYOTA3 = new HashMap<>();
        TOYOTA3.put("WHEEL_SIZE", 5);
        TOYOTA3.put("DOORS", 5);
        Map<String, Integer> BMW3 = new HashMap<>();
        BMW3.put("SIZE", 10);
        Map<String, Map<String, Integer>> three =
                Map.of("TOYOTA", TOYOTA3, "BMW", BMW3);

        Map<String, Map<String, Integer>>[] maps = new Map[]{ one, two, three };
        Map<String, Map<String, Integer>> mergedMaps = mergeMaps(maps);

        printMap(mergedMaps);
    }

    public static Map<String, Map<String, Integer>> mergeMaps(Map<String, Map<String, Integer>>[] maps) {
        Map<String, Map<String, Integer>> mergedMap = new HashMap<>();

        for(Map<String, Map<String, Integer>> map : maps) {
            for(Map.Entry<String, Map<String, Integer>> entry : map.entrySet()) {
                if(mergedMap.containsKey(entry.getKey())){
                    Map<String, Integer> mergedCarStats = mergedMap.get(entry.getKey());
                    Map<String, Integer> carStats = entry.getValue();

                    mergedCarStats.putAll(carStats);
                } else {
                    mergedMap.put(entry.getKey(), entry.getValue());
                }
            }
        }

        return mergedMap;
    }

    public static void printMap(Map<String, Map<String, Integer>> car) {
        System.out.println("{");
        for(Map.Entry<String, Map<String, Integer>> entry: car.entrySet()) {
            System.out.println(String.format("  %s = {", entry.getKey()));
            printStats(entry.getValue());
            System.out.println("  },");
        }
        System.out.println("}");
    }

    public static void printStats(Map<String, Integer> stats) {
        for(Map.Entry<String, Integer> entry : stats.entrySet()) {
            System.out.println(String.format("    '%s': %d,", entry.getKey(), entry.getValue()));
        }
    }

If you run it you will get this output:

{
  SUZUKI = {
    'WHEEL_SIZE': 2,
    'DOORS': 3,
  },
  SEAT = {
    'SPEED': 15,
    'DOORS': 4,
  },
  AUDI = {
    'SPEED': 21,
    'DOORS': 5,
    'SIZE': 4,
    'WHEELS_SIZE': 5,
  },
  TOYOTA = {
    'WHEEL_SIZE': 5,
    'DOORS': 5,
  },
  BMW = {
    'SPEED': 60,
    'SIZE': 10,
  },
}

Which is what you asked for. There are a few things to consider though. Using loops this way is inefficient because the time complexity is going to be O(n^2) as there are 2 for loops. There are built in functions for merging maps since Java 8 which could be worth exploring.

CodePudding user response:

Merge the three maps using java8

Map<String,  Map<String, Integer>> resultMap = Stream.of(map1, map2, map3)
            .flatMap(map -> map.entrySet().stream())
            .collect(Collectors.toMap(
                    Map.Entry::getKey,
                    e -> new HashMap<String,Integer>(e.getValue()),
                    (key, value) -> {key.putAll(value); return key;}
            ));

Output:

{SEAT={SPEED=15, DOORS=4}, TOYOTA={WHEELS_SIZE=5, DOORS=5}, Suzuki={WHEELS_SIZE=2, DOORS=3}, AUDI={SPEED=21, WHEELS_SIZE=5, DOORS=5, SIZE=4}, BMW={SPEED=60, SIZE=10}}

  •  Tags:  
  • java
  • Related