Home > Software design >  Grouping the Map Keys based on the part of the key in Java 8
Grouping the Map Keys based on the part of the key in Java 8

Time:04-04

I have a map which contains information as below:

"source.temp.temp1.issuer.value": "Hend",
"source.temp.temp2.issuer.value": "Ledge",
"source.temp.temp1.issuer.audence": "Legos1",
"source.temp.temp2.issuer.audence": "Legos2",
"source.temp.temp1.issuer.algp": "esc",
"source.temp.temp2.issuer.algp": "esc"

I need to do grouping based on the part of the key, i.e temp1, temp2, etc. Save them and make a list out of it. So the final result should be like this:

[
    {
        "source.temp.temp1.issuer.value": "Hend",
        "source.temp.temp1.issuer.audence": "Legos1",
        "source.temp.temp1.issuer.algp": "esc"
    },
    {
        "source.temp.temp2.issuer.value": "Ledge",
        "source.temp.temp2.issuer.audence": "Legos2",
        "source.temp.temp2.issuer.algp": "esc"
    },
    ...
]

The keys are of Object type.

CodePudding user response:

With Stream API, you can do it by utilizing the collector Collectors.groupingBy().

The classifier function that needs to be passed as an argument will replace everything after "issue" with an empty string. By default, groupingBy() collects all elements mapped to the same key into a list.

Map<String, String> source =
         Map.of("source.temp.temp1.issuer.value", "Hend",
                "source.temp.temp2.issuer.value", "Ledge",
                "source.temp.temp1.issuer.audence", "Legos1",
                "source.temp.temp2.issuer.audence", "Legos2",
                "source.temp.temp1.issuer.algp", "esc",
                "source.temp.temp2.issuer.algp", "esc");

Map<Object, List<String>> result =
        source.keySet().stream()
              .collect(Collectors.groupingBy(str -> str.replaceAll("\\.issuer(.)*", "")));

result.entrySet().forEach(System.out::println);

Output

source.temp.temp2=[source.temp.temp2.issuer.value, source.temp.temp2.issuer.algp, source.temp.temp2.issuer.audence]
source.temp.temp1=[source.temp.temp1.issuer.algp, source.temp.temp1.issuer.audence, source.temp.temp1.issuer.value]

CodePudding user response:

You can follow this, added comments in every steps.

        List<Map<String, String>> groups = source.entrySet().stream() //take maps entryset stream
            .collect(Collectors.groupingBy(e->e.getKey().contains("temp1")?"tempKey1":"tempKey2")) //group based on your term/logic Result will be <newKey, List<Entry>>
            .values().stream() //Ignore newly created key take values alone into stream again => result stream of Entry
            .map(entryList-> {
                return entryList.stream().collect(Collectors.toMap(e->e.getKey(), e->e.getValue()));
            }) //Convert entry into Map
            .collect(Collectors.toList()); //collect stream of map into List of map
    System.out.println(groups);

In groupingBy you can change the login whatever you want. Currently I hardcoded with temp1 & temp2 alone.

  • Related