Streams from Arrays – Streams
Streams from Arrays
We have seen examples of creating streams from arrays when discussing the variable arity of() method of the stream interfaces and the overloaded Arrays.stream() methods earlier in the chapter (p. 893). The sequential stream created from an array has the same order as the positional order of the elements in the array. As far as numeric streams are concerned, only an int, long, or double array can act as the data source of such a stream.
The code below illustrates creating a stream based on a subarray that is given by the half-open interval specified as an argument to the Array.stream() method, as shown at (1). The stream pipeline at (2) calculates the length of the subarray.
Stream<CD> cdStream = Arrays.stream(cdArray, 1, 4); // (1)
long noOfElements = cdStream.count(); // (2) 3
The following overloaded static methods for building sequential ordered streams from arrays are defined in the java.util.Arrays class:
static <T> Stream<T> stream(T[] array)
static <T> Stream<T> stream(T[] array, int startInclusive, int endExclusive)
Create a finite sequential ordered Stream<T> with the specified array as its source. The stream created by the second method comprises the range of values given by the specified half-open interval.
static
NumType
Stream stream(
numtype
[] array)
static
NumType
Stream stream(
numtype
[] array,
int startInclusive, int endExclusive)
NumType is Int, Long, or Double, and the corresponding numtype is int, long, or double.
Create a finite sequential ordered NumTypeStream (which is either IntStream, LongStream, or DoubleStream) with the specified array as its source. The stream created by the second method comprises the range of primitive values given by the specified half-open interval.
Building a Numeric Stream with a Range
The overloaded methods range() and rangeClosed() can be used to create finite ordered streams of integer values based on a range that can be half-open or closed, respectively. The increment size is always 1.
The following static factory methods for building numeric streams are defined only in the IntStream and LongStream interfaces in the java.util.stream package.
static
NumType
Stream range(
numtype
startInclusive,
numtype
endExclusive)
static
NumType
Stream rangeClosed(
numtype
startInclusive,
numtype
endInclusive)
NumType is Int or Long, and the corresponding numtype is int or long.
Both methods return a finite sequential ordered NumTypeStream whose elements are a sequence of numbers, where the first number in the stream is the start value of the range startInclusive and increment length of the sequence is 1. For a half-open interval, as in the first method, the end value of the range endExclusive is excluded. For a closed interval, as in the second method, the end value of the range endInclusive is included.
The range(startInclusive, endExclusive) method is equivalent to the following for(;;) loop:
for (int i = startInclusive; i < endExclusive; i++) {
// Loop body.
}
When processing with ranges of integer values, the range() methods should also be considered on par with the for(;;) loop.
The stream pipeline below prints all the elements in the CD array in reverse. Note that no terminating condition or increment expression is specified. As range values are always in increasing order, a simple adjustment can be done to reverse their order.
IntStream.range(0, CD.cdArray.length) // (1)
.forEach(i -> System.out.println(cdArray[CD.cdArray.length – 1 – i]));
The following example counts the numbers that are divisible by a specified divisor in a given range of values.
int divisor = 5;
int start = 2000, end = 3000;
long divisibles = IntStream
.rangeClosed(start, end) // (1)
.filter(number -> number % divisor == 0) // (2)
.count(); // (3)
System.out.println(divisibles); // 201
The next example creates an int array that is filled with increment values specified by the range at (1) below. The toArray() method is a terminal operation that creates an array of the appropriate type and populates it with the values in the stream (p. 971).
int first = 10, len = 8;
int[] intArray = IntStream.range(first, first + len).toArray(); // (1)
System.out.println(intArray.length + “: ” + Arrays.toString(intArray));
//8: [10, 11, 12, 13, 14, 15, 16, 17]
The example below shows usage of two nested ranges to print the multiplication tables. The inner arrange is executed 10 times for each value in the outer range.
IntStream.rangeClosed(1, 10) // Outer range.
.forEach(i -> IntStream.rangeClosed(1, 10) // Inner range.
.forEach(j -> System.out.printf(“%2d * %2d = %2d%n”,
i, j, i * j)));
}
We cordially invite the inquisitive reader to code the above examples in the imperative style using explicit loops. Which way is better is not always that clear-cut.
Leave a Reply