When to use specialised stream methods over method

2019-07-11 21:47发布

问题:

We can see that the Collectors class contains factory methods for many common aggregation operations. to name a few summingXXX, averagingXXX, maxBy, minBy.

These methods are actually duplicate functionality over calling methods on specialised streams. take for example IntStream, this has a sum(), average() , max() and min() respectively.

Same goes for DoubleStream and LongStream.

Every now and then I see people using the methods which belong to the Collectors class and specialized stream methods interchangeably.

For example, assuming we have a List<Employee> and one wants to get the average salary, you can either use the methods in the specialised primitive streams.

OptionalDouble averageUsingIntStream =
             employees.stream()
                      .mapToInt(Employee::getSalary)
                      .average();

or use the factory methods in the Collectors class.

Double averageUsingCollectors =
             employees.stream()
                      .collect(Collectors.averagingInt(Employee::getSalary));

Now, my question is what is the motivation behind this duplicate functionality and in which situation is it better to use the first approach or the second?

回答1:

The real motivation for the said factory methods in the Collectors class to exist is to be used as downstream collectors i.e. a collector that the Java runtime applies to the results of another collector. This enables one to compose together and perform more complex aggregations.

For example, there are groupingBy collectors that accept a downstream collector, collectingAndThen, partitioningBy, flatMapping (java-9) et al.

So the rule of thumb is to only use the aforementioned methods in the question as downstream collectors.

The specialised primitive streams are also more efficient so if all you want to do is compute the sum(), average() , max() or min() then I'd stick with the primitive specialisation.