7

Say I have a List of Pair objects,

List<Pair<A,B>> listOfPairs = //some list of pairs ; 

I would like to group this list into a Map<A,Set<B>>.

Currently, I can do this in two steps. The first step groups by A, and returns a Map<A,Set<Pair<A,B>> as follows:

   Map<A,Set<Pair<A,B>> intermediateStep =   listOfPairs.stream().collect(Collectors.groupingBy((Pair::getLeft), Collectors.toSet()));

I then stream the entryset of the map above and collect them into the desired end result, mainly by mapping each Pair object to its B value, and collecting them to a set:

 Map<A, Set<B>> finalResult= intermediateStep.entrySet().stream().collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue().stream().map(Pair::getRight).collect(Collectors.toSet())));

Is there a better way to achieve the desired result, perhaps in one step? In other words, the intermediate step mentioned above groups by A, but the right side of the grouping returns the entire Pair object. I'd like to group by A and point A to the set of its associated Bs in one step.

(I know that just because I could do it in one step, doesn't mean I should, because readability might suffer, but I'm curious.)

Thanks!

2 Answers 2

15

You can simplify the code by passing a mapping collector into the groupingBy collector like this:

Map<A, Set<B>> collect = 
       listOfPairs.stream()
                  .collect(Collectors.groupingBy(Pair::getLeft, 
                                Collectors.mapping(Pair::getRight,
                                       Collectors.toSet())));
Sign up to request clarification or add additional context in comments.

Comments

2

You can do it using Map.computeIfAbsent:

Map<A, Set<B>> finalResult = new HashMap<>();
listOfPairs.forEach(pair -> finalResult.computeIfAbsent(
        pair.getLeft(), 
        k -> new HashSet<>())
    .add(pair.getRight()));

If you want to preserve insertion order you can use LinkedHashMap and LinkedHashSet instead of HashMap and HashSet, respectively.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.