- 1.1. From Iterating to Stream Operations
- 1.2. Stream Creation
- 1.3. The filter, map, and flatMap Methods
- 1.4. Extracting Substreams and Combining Streams
- 1.5. Other Stream Transformations
- 1.6. Simple Reductions
- 1.7. The Optional Type
- 1.8. Collecting Results
- 1.9. Collectors
- 1.10. Reduction Operations
- 1.11. Gatherers
- 1.12. Primitive Type Streams
- 1.13. Parallel Streams
1.2. Stream Creation
You have already seen that you can turn any collection into a stream with the stream method of the Collection interface. If you have an array, use the static Stream.of method instead.
Stream<String> words = Stream.of(contents.split("\\PL+"));
In the preceding example, we make a stream from the array that the split method returns. The of method has a varargs parameter, so you can construct a stream from any number of arguments:
Stream<String> song = Stream.of("gently", "down", "the", "stream");
Use Arrays.stream(array, from, to) to make a stream from a part of an array.
To make a stream with no elements, use the static Stream.empty method:
Stream<String> silence = Stream.empty();
// Generic type <String> is inferred; same as Stream.<String>empty()
The Stream interface has two static methods for making infinite streams. The generate method takes a function with no parameters (or, technically, an object of the Supplier<T> interface). Whenever a stream value is needed, that function is called to produce a value. You can get a stream of constant values as
Stream<String> echos = Stream.generate(() -> "Echo");
or a stream of random numbers as
Stream<Double> randoms = Stream.generate(Math::random);
To produce sequences such as 0 1 2 3 . . ., use the iterate method instead. It takes a “seed” value and a function (technically, a UnaryOperator<T>) and repeatedly applies the function to the previous result. For example,
Stream<BigInteger> integers
= Stream.iterate(BigInteger.ZERO, n -> n.add(BigInteger.ONE));
The first element in the sequence is the seed BigInteger.ZERO. The second element is f(seed) which yields 1 (as a big integer). The next element is f(f(seed)) which yields 2, and so on.
To produce a finite stream instead, add a predicate that specifies when the iteration should finish:
var limit = new BigInteger("10000000");
Stream<BigInteger> integers
= Stream.iterate(BigInteger.ZERO,
n -> n.compareTo(limit) < 0,
n -> n.add(BigInteger.ONE));
As soon as the predicate rejects an iteratively generated value, the stream ends.
Finally, the Stream.ofNullable method makes a really short stream from an object. The stream has length 0 if the object is null or length 1 otherwise, containing just the object. This is mostly useful in conjunction with flatMap—see Section 1.7.7 for an example.
A number of methods in the Java API yield streams. For example, the String class has a lines method that yields a stream of the lines contained in the string:
Stream<String> greetings = "Hello\nGuten Tag\nBonjour".lines();
The Pattern class has a method splitAsStream that splits a CharSequence by a regular expression. You can use the following statement to split a string into words:
Stream<String> words = Pattern.compile("\\PL+").splitAsStream(contents);
The Scanner.tokens method yields a stream of tokens of a scanner. Another way to get a stream of words from a string is
Stream<String> words = new Scanner(contents).tokens();
The static Files.lines method returns a Stream of all lines in a file:
try (Stream<String> lines = Files.lines(path)) {
Process lines
}
Note that the try-with-resources block is necessary to close the file.
It is becoming more common to offer data as streams in the Java API. For example, Java 21 added a static availableLocales method that yields a stream of Locale objects.
To view the contents of one of the streams introduced in this section, use the toList method, which collects the stream's elements in a list. Like count, toList is a terminal operation. If the stream is infinite, first truncate it with the limit method:
IO.println(Stream.generate(Math::random).limit(10).toList());
The example program in Listing 1.2 shows the various ways of creating a stream.
