Java groupingBy : Get two (or more) groups with single Stream

Java groupingBy : Get two (or more) groups with single Stream … here is a solution to the problem.

Java groupingBy : Get two (or more) groups with single Stream

If I have to use Stream to generate two groups based on two different fields, here’s one approach I can take:

var prop1Group = beans.stream().collect(Collectors.groupingBy(Bean::getProp1));
var prop2Group = beans.stream().collect(Collectors.groupingBy(Bean::getProp2));

However, this method iterates through the list twice.
In an imperative way, I can get the same result in a single iteration like this:

var prop1Group = new HashMap<String, Set<Bean>>();
var prop2Group = new HashMap<String, Set<Bean>>();

for (var bean : beans) {
    prop1Group.computeIfAbsent(bean.getProp1(), key -> new HashSet<>()).add(bean);
    prop2Group.computeIfAbsent(bean.getProp2(), key -> new HashSet<>()).add(bean);
}

Is there a way to use a stream to accomplish the same thing declaratively without iterating twice?

Solution

Based on @Holger’s comments, I could write it more explicitly in teeing like this, but that still requires 2N

beans.stream().collect(
                Collectors.teeing(
                        groupingBy(Bean::getProp1),
                        groupingBy(Bean::getProp2),
                        List::of)) 

Related Problems and Solutions