Monday, 16 September 2013

Handling Primitives in JAVA 8

One important aspect of the Stream API that we have glossed over until now is how to handle primitive types. Java generics do not allow a primitive type to be used as a type parameter, so we cannot write Stream<int>.
 However, the eagle-eyed reader might have noticed that in the last article, we had a bit of code for finding the average age of some otters. This code actually uses primitive types over most of the pipeline, so let’s unpack this a bit and see how the primitive types are used in code like this.

First off, don’t be confused by the cast to double, which is just to ensure that Java does a proper average instead of performing integer division. The argument to map() is a lambda expression that takes in an Otter and returns an int. If we could write the code using Java generics, the lambda expression would be converted to an object that implements Function<Otter, int>. However, because Java generics do not allow this, we need to encode the fact that the return type is int in a different way—by putting it in the name of the type. So the type that is actually inferred is ToIntFunction<Otter>. This type is known as a primitive specialization of the function type, and it is used to avoid boxing and unboxing between int and Integer. This saves unnecessary generation of objects and allows us to use function types that are specific to the primitive type that’s being used. 
Let’s break down the average calculation a little more. To get the age of each otter, we use this expression:
Let’s look at the definition of the map() method that is being called: 
From this we can see that we are using the special function type ToIntFunction, and we’re also using a specialized form of Stream to represent the stream of
                         ints. ots.stream().map(o -> o.getAge())

                         IntStream map(ToIntFunction<? super T> f);

No comments:

Post a Comment