Array Type StreamsJ8 Home « Array Type Streams
We are not only limited to creating streams from collections using the stream()
method of the Collection<E>
interface as we have done in previous lessons. What if we want to create streams from arrays? Well we can and in this lesson we learn various ways of doing just that.
There are a couple of options when creating streams from arrays, using the of()
static method of the Stream<E>
interface and using the overloaded stream()
static methods of the Arrays
class.
We will start by looking at the of()
method.
Using Stream.of()
Top
Following is a TestArrayStreamsA
class to demonstrate stream creation from arrays using the of()
Static method of the Stream<E>
interface.
package info.java8;
import java.util.stream.Stream;
/* Create streams from arrays */
public class TestArrayStreamsA {
public static void main(String[] args) {
// Create an array and stream it
String[] strArray = {"one", "two", "three", "four"};
Stream<String> strArrayStream = Stream.of(strArray);
strArrayStream.forEach(System.out::print);
Stream<String> strArrayStream2 = Stream.of(strArray);
strArrayStream2.map(String::toUpperCase)
.forEach(System.out::print);
// Create an empty stream
Stream<String> wordStream = Stream.empty();
// Split into array and create stream
String sentence = "The quick brown fox jumps over the lazy dog";
wordStream = Stream.of(sentence.split("\\PL+"));
wordStream.forEach(System.out::print);
long count = wordStream.filter(e -> e.contains("o"))
.count();
System.out.println("Words containing the letter o: " + count);
// Create stream from individual entries
Stream<String> indWordsStream = Stream.of("A", "stitch", "in", "time", "saves", "nine");
indWordsStream.forEach(System.out::print);
}
}
Building and running the TestArrayStreamsA
class produces the following output:
Something went wrong! The error is telling us we are trying to reuse a stream that has already been operated upon. Looking at the code we are using the wordStream
stream twice; as mentioned in the Streams & Collections Differences section, streams are consumed after use and cannot be reused.
Removing or commenting out the line wordStream.forEach(System.out::print);
will correct the error.
Rebuilding and running the TestArrayStreamsA
class produces the following output:
The TestArrayStreamsA
class runs fine now as shown in the screenshot. We created streams from arrays using the of()
static method of the Stream<E>
interface.
We used the map()
intermediate operator, for the first time, which returns a stream consisting of the results of applying the given function to the elements of this stream. In our example this was changing all letters to upper case.
Using Arrays
Class Top
There are several overloaded static stream()
methods in the Arrays
class that we can use to convert arrays to streams, mostly dealing with numeric primitives which will be discussed in detail in the next lesson Numeric Streams, the rest we look at here:
package info.java8;
import java.util.Arrays;
import java.util.stream.Stream;
/* Create streams from arrays */
public class TestArrayStreamsB {
public static void main(String[] args) {
// Create an array and stream it
String[] strArray = {"one", "two", "three", "four"};
Stream<String> strArrayStream = Arrays.stream(strArray);
strArrayStream.forEach(System.out::print);
Stream<String> strArrayStream2 = Arrays.stream(strArray);
strArrayStream2.map(String::toUpperCase)
.forEach(System.out::print);
// Split into array and create stream
String sentence = "The quick brown fox jumps over the lazy dog";
Stream<String> wordStream = Arrays.stream(sentence.split("\\PL+"));
long count = wordStream.filter(e -> e.contains("o"))
.count();
System.out.println("Words containing the letter o: " + count);
// Create stream from individual entries
Stream<String> indWordsStream = Arrays.stream(new String[]{"A", "stitch", "in", "time", "saves", "nine"});
indWordsStream.forEach(System.out::print);
// Create stream from parts of an array
Stream<String> indWordsStream2 = Arrays.stream(new String[]{"A", "stitch", "in", "time", "saves", "nine"}, 1, 4);
indWordsStream2.forEach(System.out::print);
}
}
Running the TestArrayStreamsB
class produces the following output:
We created streams from arrays using the stream()
static method of the Arrays
class and the overloaded version that takes start (inclusive) and end (exclusive) positions within the array .
Stream.of()
OR Arrays.stream()
? Top
So which should we use Stream.of()
or Arrays.stream()
? On the surface they seem to do much the same thing but there are subtle differences dependant upon the type used. With our examples so far we have been creating streams of objects, in our case String
objects and in these cases both methods return a stream of objects Stream<T>
. But what if we wanted to stream a primitive type array, how would this work?
Lets code this up and find out using a simple int primitive array!
package info.java8;
import java.util.Arrays;
import java.util.stream.Stream;
/* Create streams from arrays */
public class TestArrayStreamsC {
public static void main(String[] args) {
// Creating a primitive int array
int[] intArray = { 1, 2, 3, 4, 5 };
// Arrays.stream()
Stream<int[]> stream = Arrays.stream(intArray);
// Displaying elements in Stream
stream.forEach(System.out::println);
// Stream.of
Stream<int[]> stream2 = Stream.of(intArray);
// Displaying elements in Stream2
stream2.forEach(System.out::println);
}
}
Building the TestArrayStreamsC
class produces the following output:
Something went wrong! The compiler is telling us about incompatible types and is expecting an IntStream
.
Looking through the java documentation for the Arrays
class it seems we have inadvertently used another overloaded stream()
method that accepts an int[]
array, that being stream(int[])
. This method expects to return an IntStream
object like the compiler is telling us. There are also overloaded stream()
methods that accept a double[]
array and return a DoubleStream
and long[]
array and return a LongStream
Lets change the line:
Stream<int[]> stream = Arrays.stream(intArray);
to accept an IntStream
object as follows:
IntStream stream = Arrays.stream(intArray);
Rebuilding and running the TestArrayStreamsC
class produces the following output:
The TestArrayStreamsC
class runs fine now as shown in the screenshot. There is still a problem though as we are just seeing an object reference for the Stream.of()
output.
For object type arrays the overloaded Stream.of
static method that takes varargs is called. This calls the Arrays.stream()
method under the bonnet, as shown below, so the return types are the same.
However, for primitive type arrays the overloaded Stream.of
method that takes an object is called (arrays are objects) and this returns a stream containing a single object, in our case Stream<int[]>
.
To extract the values and print out the contents we will have to flatten the stream using the flatMapToInt()
intermediate operation of the Stream<T>
interface, which returns an IntStream
consisting of the results of replacing each element of this stream with the contents of a mapped stream, produced by applying the provided mapping function to each element.
There are also flatMapToDouble()
and flatMapToLong()
versions of this method.
Following is the revised code.
package info.java8;
import java.util.Arrays;
import java.util.stream.IntStream;
import java.util.stream.Stream;
/* Create streams from arrays */
public class TestArrayStreamsC {
public static void main(String[] args) {
// Creating a primitive int array
int[] intArray = { 1, 2, 3, 4, 5 };
// Arrays.stream()
IntStream stream = Arrays.stream(intArray);
// Displaying elements in Stream
stream.forEach(System.out::println);
// Stream.of
Stream<int[]> stream2 = Stream.of(intArray);
// Flatten Stream<int[]> into IntStream
IntStream stream3 = stream2.flatMapToInt(Arrays::stream);
// Displaying elements in Stream2
stream3.forEach(System.out::println);
}
}
Rebuilding the TestArrayStreamsB
class produces the following output:
OK this all works fine now. So what have we learnt?
If your streaming arrays of objects then the Stream.of
static method and the Arrays.stream()
method both end up using Arrays.stream()
.
If you're streaming primitives use the Arrays.stream()
variants that were built for this purpose.
If you want to stream boolean
, byte
, char
and short
primitives use an IntStream
.
If you want to stream float
primitives use a DoubleStream
.
Related Quiz
Streams Quiz 4 - Array Type Streams Quiz
Lesson 4 Complete
In this lesson we looked at various ways in which we can create streams from arrays.
What's Next?
In the next lesson we look at numeric streams.