Home > Software design >  How to Merge the Duplicate Values and its Keys present in the HashMap
How to Merge the Duplicate Values and its Keys present in the HashMap

Time:10-19

HashMap<String, String> map = new HashMap<String, String>();
HashMap<String, String> newMap = new HashMap<String, String>();

map.put("A","1");
map.put("B","2");
map.put("C","2");
map.put("D","1");

Expected Output: "AD", "1" and "BC", "2" present inside the newMap which means, if the data values were same it needs combine its keys to have only one data value by combining its keys inside the newMap created how to achieve this in Java?

CodePudding user response:

You want to group by the "integer" value using Collectors.groupingBy and collect the former keys as a new value. By default, grouping yields in List. You can further use downstream collector Collectors.mapping and another downstream collector Collectors.reducing to map and concatenate the individual items (values) as a single String.

Map<String, String> groupedMap = map.entrySet().stream()
        .collect(Collectors.groupingBy(
                Map.Entry::getValue,
                Collectors.mapping(
                        Map.Entry::getKey,
                        Collectors.reducing("", (l, r) -> l   r))));
{1=AD, 2=BC}

Now, you can switch keys with values for the final result:

Map<String, String> newMap = groupedMap.entrySet().stream()
        .collect(Collectors.toMap(
                Map.Entry::getValue, 
                Map.Entry::getKey));
{BC=2, AD=1}

It is possible, put it all together using Collectors.collectingAndThen (matter of taste):

Map<String, String> newMap = map.entrySet().stream()
        .collect(Collectors.collectingAndThen(
                Collectors.groupingBy(
                        Map.Entry::getValue,
                        Collectors.mapping(
                                Map.Entry::getKey,
                                Collectors.reducing("", (l, r) -> l   r))),
                m -> m.entrySet().stream()
                        .collect(Collectors.toMap(
                                Map.Entry::getValue, 
                                Map.Entry::getKey))));

CodePudding user response:

Based on logic:

  1. Loop through your map

  2. For each value, get the corresponding key from the new map (based on the value)

  3. If the new map key exists, remove it and put it again with the extra letter at the end

  4. If not exists, just put it without any concatenation.

    for (var entry : map.entrySet()) 
    {
        String newMapKey = getKey(newMap, entry.getValue());
        if (newMapKey != null) 
        {
            newMap.remove(newMapKey);
            newMap.put(newMapKey   entry.getKey(), entry.getValue());
            continue;
        }
        newMap.put(entry.getKey(), entry.getValue());
    }
    

The extra method:

    private static String getKey(HashMap<String, String> map, String value) 
    {
        for (String key : map.keySet())
            if (value.equals(map.get(key)))
                return key;

        return null;
    }

{BC=2, AD=1}

CodePudding user response:

Using Java 8

You can try the below approach in order to get the desired result.

Code:

  public class Test {
    public static void main(String[] args) {
            HashMap<String, String> map = new HashMap<>();
            Map<String, String> newMap;

            map.put("A","1");
            map.put("B","2");
            map.put("C","2");
            map.put("D","1");

            Map<String, String> tempMap = map.entrySet().stream()
                    .collect(Collectors.groupingBy(Map.Entry::getValue,
                            Collectors.mapping(Map.Entry::getKey,Collectors.joining(""))));

            newMap = tempMap.entrySet().stream().sorted(Map.Entry.comparingByValue())
                    .collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey,(a,b) -> a, LinkedHashMap::new));
            System.out.println(newMap);
        }
}

Output:

{AD=1, BC=2}
  • Related