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.