Creating Streams
An array does not have a stream() method, so you cannot create a stream by calling stream() on the array itself.
Why Streams Need a Starting Point
An array holds a fixed group of values, and many programs need to process every value in that group. Java offers streams as a way to work with such a group. A stream is a way of processing a sequence of values, but it does not appear out of nowhere. Every stream needs a starting point that supplies the values it will work on. This article is about that starting point: how a stream is born from an array or from a collection.
What do you think happens?
You have an int array named A. Which expression creates a stream from it: A.stream() or Arrays.stream(A)? Make your guess before reading on.
Reveal answer
Arrays.stream(A)
An array does not have a stream() method, so you cannot create a stream by calling stream() on the array itself. The ability to create a stream from an array belongs to the static method stream in the class Arrays, which comes from the package java.util. Because the method is static, you call it on the class and pass the array in as the argument.
Tracing the Stream-Creation Line
The program below creates one stream from an array and three from a collection. As you read it, keep one question in mind: at which line does a stream first appear, and does the source passed to it match what you expected? Each stream-creation line is the boundary between the world of arrays and collections and the world of streams.
- Line 6 declares the array A; it is the source for the first stream.
- Line 7 declares the collection c; it is the source for the other three streams.
- Line 9 creates a stream from the array by passing A to the static method
Arrays.stream. - Line 10 creates a sequential stream from the collection with
stream(). - Line 11 creates a parallel stream from the same collection with
parallelStream(). - Line 12 creates a parallel stream by calling
parallel()on a sequential stream.
Read the program one stream-creation line at a time and compare each result with its source.- 1The array A is the only source for the first stream, and it is passed as the argument to
Arrays.stream. The result is a stream built from A's elements. - 2The collection c is the source for the next three lines. Each call is made on c itself, so the source is the collection rather than an argument.
- 3The method name in each call decides the kind of stream:
stream()gives a sequential stream,parallelStream()gives a parallel stream. - 4The last line starts from a sequential stream and calls
parallel()on it, so it also ends with a parallel stream, through one extra step.
Arrays Create Streams Through a Static Method
The ability to create a stream from an array is not a method attached to the array. An array does not have a stream() method, so the call A.stream() cannot be used to create a stream. Instead, the stream comes from a static method named stream in the class Arrays, which is part of the package java.util.
Arrays.stream(A) is the expression that creates a stream from an array. The class name Arrays tells Java where to look for the method, the method name stream tells Java what to do, and the argument A tells Java which array to use. Because the method is static, you call it on the class itself and pass the array in.
Each part of the expression has a job, and changing any one of them changes what the expression means. Keep the array as the argument. The stream you get back is created from that array, so it holds the values the array holds.
Creating Streams from Collections
A collection serves as the source of values for a stream, and this applies to lists, sets, and any other collection. You do not need a different technique for each type of collection. What changes from one creation call to another is not the kind of collection but the kind of stream that comes out of it.
Given a collection named c, there are two direct ways to get a stream. The method name tells you which one you are asking for, and the two calls begin from the same collection and draw the same values.
Deriving a Parallel Stream with parallel()
There is a second route to a parallel stream. You can first create a sequential stream with stream() and then call parallel() on it. The result is a parallel stream, so this route reaches the same destination as parallelStream(), with one extra step. Both forms are valid, and you will see the two-step form in code that wants the sequential start visible in the source.
twoStepstarts from a sequential stream and then changes it withparallel().oneStepreaches a parallel stream directly withparallelStream().
Mistakes When Creating Streams
The mistakes below come up most often when a stream is created from the wrong source or with the wrong name.
Common mistake Calling stream() directly on an array
What it looks likeint[] A = {4, 8, 15}; var s = A.stream();Why it failsAn array does not have a
stream()method, so the array itself cannot create a stream this way.Do this insteadPass the array to the static method: var s = Arrays.stream(A);Common mistake Expecting different values from stream() and parallelStream()
Why it failsBoth calls start from the same collection and draw the same values. The difference is the kind of stream built.
Do this insteadCompare the method names to decide the kind of stream, and expect the same source values from either call.
Common mistake Assuming parallel() creates a sequential stream
Why it failsparallel()is the route to a parallel stream, even when it is applied to a sequential stream.Do this insteadRead c.stream().parallel() as ending in a parallel stream.Common mistake Forgetting that the method name sets the stream kind
Why it failsThe kind of stream is decided by the creation call, so the name you read is the only signal of the kind.
Do this insteadRead the creation line and name the kind before reading any later processing code.
Locating the Departing Line
Now apply the trace method to a program that contains an error. Read the stream-creation lines in order and find the first one where the result is not what you expected.
- Line 1 declares the array A.
- Line 2 creates a stream from A correctly by passing it to
Arrays.stream. - Line 3 tries to call
stream()on the array itself.
Finding the Line Where Stream Creation Departs
In the program above, which line first produces a stream-creation result that differs from what is expected, and why?
- 1Check the source of each stream
The array A is the source for both creation lines, so the question is which form is valid for an array.
- 2Compare line 2 with the expected form
Arrays.stream(A)is the static method that creates a stream from an array, so line 2 matches what is expected. - 3Compare line 3 with the expected form
A.stream()asks the array to create a stream through its ownstream()method, which the array does not have. Line 3 is the first line where the expected stream does not appear. - 4Fix the line
Replace the call with
Arrays.stream(A), passing the array as the argument.
Line 3, the call A.stream(), is the departing line. The correction is var second = Arrays.stream(A);
Predicting Creation Calls
Given a collection named names, which call produces a parallel stream: names.stream() or names.parallelStream()? Explain your choice in terms of the method name.
Hints
- Look at the method name in each call.
- The name
parallelStreamasks for the parallel kind; the name stream asks for the sequential kind.
A program has an int array named nums and a list named items. Write one stream-creation line for each source: a sequential stream from nums, and a parallel stream derived from a sequential stream of items. Then identify which of your lines would be wrong if you had written nums.stream() instead of the correct form.
Hints
- An array's stream comes from the static method in the class Arrays, passed the array as its argument.
- A two-step parallel stream starts with
stream()and then callsparallel().
Key Takeaways
- An array does not have a
stream()method, so a stream from an array is created with the static methodArrays.stream(A)from packagejava.util. - A collection such as a list or a set is the source for a stream. Calling
c.stream()gives a sequential stream, andc.parallelStream()gives a parallel stream from the same collection. - The method name decides the kind of stream, so read the creation call before reasoning about how the stream is processed.
c.stream().parallel() is a two-step route that also yields a parallel stream from a sequential start.- When a stream-based result is wrong, trace the stream-creation line first and compare it with the source you passed in.