Home > Articles

Streams

This chapter is from the book

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.

Listing 1.2 v2ch01/streams/CreatingStreams.java

InformIT Promotional Mailings & Special Offers

I would like to receive exclusive offers and hear about products from InformIT and its family of brands. I can unsubscribe at any time.