Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is the combiner of the Collector interface not consistent with the overloaded collect method?

Tags:

There is an overload method, collect(), in interface Stream<T> with the following signature:

<R> R collect(Supplier<R> supplier,           BiConsumer<R,? super T> accumulator,           BiConsumer<R,R> combiner) 

There is another version of collect(Collector<? super T,A,R> collector), which receives an object with the previous three functions. The property of the interface Collector corresponding to the combiner has the signature BinaryOperator<A> combiner().

In the latter case, the Java API 8 states that:

The combiner function may fold state from one argument into the other and return that, or may return a new result container.

Why does the former collect method not receive a BinaryOperator<R> too?

like image 601
Miguel Gamboa Avatar asked May 18 '15 17:05

Miguel Gamboa


People also ask

What is a combiner for in reduce Java?

The combiner function may fold state from one argument into the other and return that, or may return a new result container. Returns: a function which combines two partial results into a combined result.

What is collect collectors toList ())?

The toList() method of Collectors Class is a static (class) method. It returns a Collector Interface that gathers the input data onto a new list. This method never guarantees type, mutability, serializability, or thread-safety of the returned list but for more control toCollection(Supplier) method can be used.

What implementation of list does the collectors toList () create?

toList(), collects the elements into an unmodifiable List. Though the current implementation of the Collectors. toList() creates a mutable List, the method's specification itself makes no guarantee on the type, mutability, serializability, or thread-safety of the List. On the other hand, both Collectors.

What is a downstream collector?

The term downstream in the documentation refers to one Collector accepting a second Collector as an argument. The argument is applied downstream (after) the Collector that accepts it. In other words, the downstream Collector is applied to the result of the upstream Collector. In your example, Collectors.


1 Answers

The "inline" (3-arg) version of collect is designed for when you already have these functions "lying around". For example:

ArrayList<Foo> list = stream.collect(ArrayList::new,                                       ArrayList::add,                                      ArrayList::addAll); 

Or

BitSet bitset = stream.collect(BitSet::new,                                 BitSet::set,                                BitSet::or); 

While these are just motivating examples, our explorations with similar existing builder classes was that the signatures of the existing combiner candidates were more suited to conversion to BiConsumer than to BinaryOperator. Offering the "flexibility" you ask for would make this overload far less useful in the very cases it was designed to support -- which is when you've already got the functions lying around, and you don't want to have to make (or learn about making) a Collector just to collect them.

Collector, on the other hand, has a far wider range of uses, and so merits the additional flexibility.

like image 168
Brian Goetz Avatar answered Sep 21 '22 07:09

Brian Goetz