ab11
ab11

Reputation: 20090

How to sort this HashMap while flattening/grouping it, using streams?

I asked a question yesterday flattening/grouping a HashMap. I got a great response that suggested I do this.

return new ArrayList<>(map.entrySet().stream()
    .collect(Collectors.groupingBy(
        Map.Entry::getValue,
        Collectors.mapping(Map.Entry::getKey, Collectors.joining(","))))
    .values())

However, I would like my list of comma separated characters to be sorted alphabetically. The comments suggested I try using TreeMap::new as an argument to groupingBy(), but when I try this my list of characters remains unsorted:

return new ArrayList<>(map.entrySet().stream()
    .collect(Collectors.groupingBy(
        Map.Entry::getValue,
        TreeMap::new,
        Collectors.mapping(Map.Entry::getKey, Collectors.joining(","))))
    .values())

Below is my original question with a link to the post.

Given mapping of letters to numbers, I would like to return a list of Strings, where each String is a comma delimited list of the letters grouped by their associated number.

For this map

    Map<String, Integer> map = new HashMap<String, Integer>();
    map.put("A", 1);
    map.put("B", 2);
    map.put("C", 4);
    map.put("D", 1);
    map.put("E", 1);
    map.put("F", 2);

I would like to return a List containing:

"A,D,E" "B,F", "C"

Any suggestions how this can be accomplished using the 1.8 streaming functions?

How to flatten and group this HashMap, using streams?

Upvotes: 2

Views: 171

Answers (3)

Not a JD
Not a JD

Reputation: 1902

This might also work for you:

return new ArrayList<>(map.entrySet().stream()
        .collect(Collectors.groupingBy(
                Map.Entry::getValue,
                TreeMap::new,
                Collectors.mapping(Map.Entry::getKey, Collectors.collectingAndThen(Collectors.toList(), l -> {
                    Collections.sort(l);
                    return String.join(",", l);
                }))))
        .values());

Upvotes: 1

Naman
Naman

Reputation: 31878

Tweaking one of the answers to the linked question, this should do the trick for what you're looking for:

List<String> result = map.entrySet().stream()
        .collect(Collectors.groupingBy(Map.Entry::getValue))
        .values().stream()
        .map(e -> e.stream()
                .map(Map.Entry::getKey)
                .sorted() // <<< modified this
                .collect(Collectors.joining(",")))
        .collect(Collectors.toList());

Upvotes: 0

Leo Aso
Leo Aso

Reputation: 12463

Turn the map to a TreeMap before performing the operation, and the keys will be in order in the output.

//                         * here
return new ArrayList<>(new TreeMap(map).entrySet().stream()
.collect(Collectors.groupingBy(
    Map.Entry::getValue,
    TreeMap::new,
    Collectors.mapping(Map.Entry::getKey, Collectors.joining(","))))
.values())

Upvotes: 2

Related Questions