Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why don't primitive Stream have collect(Collector)?

I'm writing a library for novice programmers so I'm trying to keep the API as clean as possible.

One of the things my Library needs to do is perform some complex computations on a large collection of ints or longs. There are lots of scenarios and business objects that my users need to compute these values from, so I thought the best way would be to use streams to allow users to map business objects to IntStream or LongStream and then compute the computations inside of a collector.

However IntStream and LongStream only have the 3 parameter collect method:

collect(Supplier<R> supplier, ObjIntConsumer<R> accumulator, BiConsumer<R,R> combiner) 

And doesn't have the simplier collect(Collector) method that Stream<T> has.

So instead of being able to do

Collection<T> businessObjs = ... MyResult result = businessObjs.stream()                               .mapToInt( ... )                               .collect( new MyComplexComputation(...)); 

I have to do provide Suppliers, accumulators and combiners like this:

MyResult result = businessObjs.stream()                               .mapToInt( ... )                               .collect(                                    ()-> new MyComplexComputationBuilder(...),                                   (builder, v)-> builder.add(v),                                   (a,b)-> a.merge(b))                               .build(); //prev collect returns Builder object 

This is way too complicated for my novice users and is very error prone.

My work around is to make static methods that take an IntStream or LongStream as input and hide the collector creation and execution for you

public static MyResult compute(IntStream stream, ...){        return .collect(                          ()-> new MyComplexComputationBuilder(...),                         (builder, v)-> builder.add(v),                         (a,b)-> a.merge(b))                .build(); } 

But that doesn't follow the normal conventions of working with Streams:

IntStream tmpStream = businessObjs.stream()                               .mapToInt( ... );   MyResult result = MyUtil.compute(tmpStream, ...); 

Because you have to either save a temp variable and pass that to the static method, or create the Stream inside the static call which may be confusing when it's is mixed in with the other parameters to my computation.

Is there a cleaner way to do this while still working with IntStream or LongStream ?

like image 682
dkatzel Avatar asked May 18 '15 18:05

dkatzel


People also ask

Can you use streams with primitives?

Primitive StreamsStreams primarily work with collections of objects and not primitive types. Fortunately, to provide a way to work with the three most used primitive types – int, long and double – the standard library includes three primitive-specialized implementations: IntStream, LongStream, and DoubleStream.

What is the use of collect method in stream?

The collect() method in Stream API collects all objects from a stream object and stored in the type of collection. The user has to provide what type of collection the results can be stored. We specify the collection type using the Collectors Enum.

Can you have primitive type data in a stream E >?

What lies behind is that: Java generics cannot work with primitive types: it is possible to have only List<Integer> and Stream<Integer> , but not List<int> and Stream<int>

What is a stream collector?

The Stream. collect() is one of the Java 8's Stream API's terminal methods. It allows us to perform mutable fold operations (repackaging elements to some data structures and applying some additional logic, concatenating them, etc.) on data elements held in a Stream instance.


Video Answer


1 Answers

We did in fact prototype some Collector.OfXxx specializations. What we found -- in addition to the obvious annoyance of more specialized types -- was that this was not really very useful without having a full complement of primitive-specialized collections (like Trove does, or GS-Collections, but which the JDK does not have). Without an IntArrayList, for example, a Collector.OfInt merely pushes the boxing somewhere else -- from the Collector to the container -- which no big win, and lots more API surface.

like image 85
Brian Goetz Avatar answered Sep 20 '22 18:09

Brian Goetz