What's the difference between Stream.map(…) an

2020-02-26 07:40发布

问题:

I've noticed many functionalities exposed in Stream are apparently duplicated in Collectors, such as Stream.map(Foo::bar) versus Collectors.mapping(Foo::bar, ...), or Stream.count() versus Collectors.counting(). What's the difference between these approaches? Is there a performance difference? Are they implemented differently in some way that affects how well they can be parallelized?

回答1:

The collectors that appear to duplicate functionality in Stream exist so they can be used as downstream collectors for collector combinators like groupingBy().

As a concrete example, suppose you want to compute "count of transactions by seller". You could do:

Map<Seller, Long> salesBySeller = 
    txns.stream()
        .collect(groupingBy(Txn::getSeller, counting()));

Without collectors like counting() or mapping(), these kinds of queries would be much more difficult.



回答2:

There's a big difference. The stream operations could be divided into two group:

  • Intermediate operations - Stream.map, Stream.flatMap, Stream.filter. Those produce instance of the Stream and are always lazy, e.g. no actual traversal of the Stream elements happens. Those operations are used to create transformation chain.
  • Terminal operations - Stream.collect, Stream.findFirst, Stream.reduce etc. Those do the actual work, e.g. perform the transformation chain operations on the stream, producing a terminal value. Which could be a List, count of element, first element etc.

Take a look at the Stream package summary javadoc for more information.