Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Primitive stream vs object stream and actual boxing that occurs

So I understand you can have object streams, i.e. Stream<T> and specialist primitive streams, e.g. IntStream, DoubleStream, etc. One of the benefits of the latter is to avoid autoboxing.

Also if we take IntStream as an example, it has specialised operations such as filter that accepts an IntPredicate.

I wondered if I had an IntStream vs a Stream<Integer> at which point you're saving on boxing, e.g.

intstream.filter(x -> x >= 50).forEach(x -> System.out.println(x));

vs

stream.filter(x -> x >= 50).forEach(x -> System.out.println(x));

In the first example, there is no boxing or unboxing that I can see. In the second example where is the boxing / unboxing occurring? Because if stream is a Stream<Integer> and the filter accepts a Predicate<Integer> then surely there's no need to box/unbox, and the same for IntConsumer vs Consumer<T>?

like image 207
Tranquility Avatar asked Feb 04 '16 18:02

Tranquility


2 Answers

The unboxing happens inside the predicate: in stream.filter(x -> x >= 50), the Predicate essentially becomes (Integer x) -> x.intValue() >= 50, and intValue() is the unboxing step. Additionally, System.out.println does some unboxing itself, in the implementation of Integer.toString that ends up being called.

like image 89
Louis Wasserman Avatar answered Sep 28 '22 00:09

Louis Wasserman


With Stream<Integer> your stream is already boxed. So depending on how you created it there are several possibilities:

  • You have initially boxed values. For example, you had List<Integer> list as the input and wrote:

    stream = list.stream();
    
  • You boxed your values when creating the stream. For example, you created it like this:

    stream = Stream.iterate(1, x -> x+1);
    

    In this case the first argument is boxed to Integer.valueOf(1) and unboxing/boxing also occurs on every lambda (which is UnaryOperator<Integer>) invocation. So effectively you have:

    stream = Stream.iterate(Integer.valueOf(1), x -> Integer.valueOf(x.intValue()+1));
    
  • You boxed your source explicitly via upstream intermediate operation. For example:

    stream = IntStream.range(0, 1000).boxed();
    

    In this case boxing is performed inside the .boxed() operation (which is a shortcut for .mapToObj(Integer::valueOf)).

like image 27
Tagir Valeev Avatar answered Sep 28 '22 00:09

Tagir Valeev