Stream groupingBy values

1k views Asked by At

Is there a non-terminal version of groupingBy or some other neat way to stream through the resulting Map entries/values?

I find myself wanting to stream through the values after groupingBy but the best I could come up with is not pretty:

    StreamEx.ofValues(
            StreamEx.of(0, 1, 2, 4).groupingBy(i -> i % 2)
    ).mapToInt(ii -> IntStreamEx.of(ii).sum())
    // RESULT: [6, 1]
2

There are 2 answers

0
Tunaki On BEST ANSWER

Doing this in a single Stream pipeline would probably require the wanted operation to act like a full barrier: in order to group the values, we need to process them all to see which values are even and odd (and be able to sum them).

As such, it is probably preferable to use a temporary data structure to hold the count of even and odd values, which in this case would be a Map<Integer, Integer> or even a Map<Boolean, Integer> (where, for example, the key would be true for even values and false for odd values, using Collectors.partitioningBy).


Note that you don't need to use the StreamEx library here. You can do this directly the Stream API:

public static void main(String[] args) {
    Map<Integer, Integer> map =
      Stream.of(0, 1, 2, 4)
            .collect(Collectors.groupingBy(
               i -> i % 2,
               Collectors.summingInt(i -> i)
            ));

    Stream<Integer> stream = map.values().stream();
}
0
rednoah On

summingInt is probably best solution for this specific question.

I guess I oversimplified the problem by using ints in my example. My actual problem was about merging objects, not int values. I found collectingAndThen to be quite useful. It works like this:

Function<List<Integer>, Integer> merge = ii -> ii.stream().mapToInt(i -> i).sum();
Stream.of(0, 1, 2, 4).collect(groupingBy(i -> i % 2, collectingAndThen(toList(), merge))).values();