Monday, 9 January 2017

Primitive type streams in Java Stream API

If you have gone through the post Stream API in Java 8 one thing you would have noticed is that Streams work on object references. They can’t work on primitive types because of that many times people use Stream<Integer>, Stream<Long> or Stream<Double> in order to wrap primitive types into a wrapper object.

In Java Stream API Examples you will see an example where integers are collected in Stream<Integer>. But, that is not an efficient way to work with primitive types as you need to wrap them into wrapper objects. Instead you should use primitive specializations of Stream like IntStream, LongStream, and DoubleStream that can store primitive values.

Apart from int you can use IntStream for short, char, byte, and boolean. For float DoubleStream can be used.

Creating primitive type Streams

  1. You can use of() method to create primitive type Stream. It has two variants, for IntStream these two variants are -
    • static IntStream of(int t) - Returns a sequential IntStream containing a single element.
    • static IntStream of(int... values) - Returns a sequential ordered stream whose elements are the specified values.

    As Example -

    System.out.println("--- IntStream ---");
    IntStream is = IntStream.of(3, 4, 5, 6);
    is.forEach(System.out::println);
    

    Output

    --- IntStream ---
    3
    4
    5
    6
    

    It works the same way for LongStream and DoubleStream.

  2. Using Arrays.stream() method

    It has two variants. For DoubleStream these two variants are -

    • public static DoubleStream stream(double[] array) - Returns a sequential DoubleStream with the specified array as its source.
    • public static DoubleStream stream(double[] array, int startInclusive, int endExclusive) - Returns a sequential DoubleStream with the specified range of the specified array as its source.

    It works the same way for IntStream and LongStream.

    Example of Arrays.stream()

    System.out.println("--- DoubleStream ---");
    double[] num = {3.0, 4.7, 5.2, 6.8};
    DoubleStream numStream = Arrays.stream(num);
    numStream.forEach(System.out::println);
    System.out.println("--- With Specified range ---");
    numStream = Arrays.stream(num, 0, 2);
    numStream.forEach(System.out::println);
    

    Output

    --- DoubleStream ---
    3.0
    4.7
    5.2
    6.8
    --- With Specified range ---
    3.0
    4.7
    

    In the second variant since second argument is 2 and the end index passed is exclusive so effective range for the stream is 0 – 1.

  3. Using range() and rangeClosed() methods
    • static IntStream range(int startInclusive, int endExclusive) - Returns a sequential ordered IntStream from startInclusive (inclusive) to endExclusive (exclusive) by an incremental step of 1.
    • static IntStream rangeClosed(int startInclusive, int endInclusive) - Returns a sequential ordered IntStream from startInclusive (inclusive) to endInclusive (inclusive) by an incremental step of 1.

    It works the same way for LongStream. Note that these methods will work with IntStream and LongStream, not provided for DoubleStream.

    As example – If you want a stream with 1000 integers, 1 – 1000.

    IntStream thousandInt = IntStream.rangeClosed(1, 1000);
    

    Since you can create a range of numbers, these methods help with testing with large data. See an example in Parallel Stream in Java Stream API.

Transforming Stream to primitive type Stream

Stream interface provides methods mapToInt, mapToDouble and mapToLong that can be used to transform stream of objects to a stream of primitive types.

Infact reduction operations such as average, sum, min (without specifying a comparator), max (without specifying a comparator) are not provided for Stream with object references. Since these operations are used quite frequently with streams so you will do this transformation using mapToxxx methods a lot if time.

As example – If you have a list of employee objects and you want to get the maximum salary you can do it using mapToInt method like this -

OptionalInt maxSalary = empList.parallelStream().mapToInt(e -> e.getSalary()).max();

If you want total amount given to all employees then you can sum the salaries like this -

int totalSalary = empList.parallelStream().mapToInt(e -> e.getSalary()).sum();

If you have noticed the first example returns the result of type OptionalInt. Methods that return result of type Optional in Stream with objects will return result of type OptionalInt, OptionalLong and OptionalDouble. In these classes there are specific methods like getAsInt(), getAsLong() and getAsDouble() rather than a generic get() method present in Optional class.

Transforming primitive type Stream to Stream of objects

All the primitive type Streams have boxed() method that will return a Stream consisting of the elements of this stream wrapped as object.

Thus used with DoubleStream, boxed() method will return a Stream consisting of the elements of this stream, each boxed to a Double i.e. Stream<Double>.

Same way for IntStream and LongStream you will get a Stream having elements of type Integer and Long respectively, i.e. Stream<Integer> and Stream<Long>.

As example -

Stream<Integer> iStream = IntStream.of(3, 4, 5, 6).boxed();

That's all for this topic Primitive type streams in Java Stream API. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Stream API in Java 8
  2. Reduction Operations in Java Stream API
  3. Lambda expressions in Java 8
  4. Method reference in Java 8
  5. Functional interface annotation in Java 8

You may also like -

>>>Go to Java advance topics page

No comments:

Post a Comment