Stream.of()

Create a sequential, ordered stream from a few values or an object array, and avoid the primitive-array trap that gives you a stream of one element.

Signature
static <T> Stream<T> of(T t)
@SafeVarargs static <T> Stream<T> of(T... values)
  • Added in Java Java 8

Parameters

ParameterTypeDescription
$tTThe single element of the stream (the one-argument overload). It may be null; use Stream.ofNullable to get an empty stream for null instead.
$valuesT...The elements of the stream (the varargs overload). An object array passed here is spread into its elements; a primitive array is not.

Return value

Stream<T>A sequential, ordered stream whose elements are the given values, in argument order.

Errors

NullPointerException if the varargs array itself is null. A null element is allowed and becomes a null in the stream.

Stream.of is the quickest way to make a stream from values you already have in your hand. It has two overloads: one takes a single element, the other takes varargs. Both return a sequential, ordered stream, so the elements come out in the order you wrote them.

When to use it

Use it for a fixed, small set of values: the allowed sort fields of an endpoint, a handful of IDs in a test, or several lists you want to process as one. When you already hold a collection, call collection.stream() instead; wrapping the list in Stream.of(list) gives you a stream with exactly one element, the list itself.

Arrays: object versus primitive

An object array such as String[] matches the varargs parameter directly, so Stream.of(tags) is a stream of the strings. A primitive array such as int[] cannot be a T[], because generics need reference types. It is treated as one object, and you get a Stream<int[]> with a single element. This is the most common surprise with Stream.of. For primitives use IntStream.of(...), LongStream.of(...) or Arrays.stream(array), which also avoid boxing.

Nulls and optional values

Stream.of(x) with a null x gives a stream holding one null, which later fails in any mapper that calls a method on it, or in findFirst. Stream.ofNullable(x) (Java 9) gives an empty stream for null and a one-element stream otherwise. Combined with flatMap it drops absent values from a list of optional request headers or lookups.

One use only

A stream is a one-shot pipeline, not a container. Storing a Stream in a field or a variable and running two terminal operations on it throws IllegalStateException with the message stream has already been operated upon or closed. Keep the source (a list, or a Supplier<Stream<T>>) and create a new stream each time.

Joining several sources

Stream.of(a, b, c).flatMap(List::stream) concatenates any number of lists in order. For exactly two streams, Stream.concat(s1, s2) does the same job. Nesting concat calls deeply is discouraged by its documentation, because it builds a deep chain that can overflow the stack; the Stream.of(...).flatMap(...) form has no such limit.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Validate a sort parameter against the fixed set of field names an endpoint allows.
  • Merge results from a cache, a database query and a remote call into one stream before mapping them to response objects.
  • Collect only the correlation headers a request actually sent by flat-mapping each one through Stream.ofNullable.

Frequently asked questions

What is the difference between Stream.of and Arrays.stream?

For an object array they behave the same, since Stream.of(T...) calls Arrays.stream internally. For a primitive array they differ: Arrays.stream(int[]) returns an IntStream of the numbers, while Stream.of(int[]) returns a Stream<int[]> with the whole array as its only element. Arrays.stream also has an overload that takes a start and end index.

Why do I get 'stream has already been operated upon or closed'?

A stream can run only one terminal operation. If you store a Stream in a variable and call toList() and then count() on it, the second call throws IllegalStateException. Create a new stream from the source each time, for example with a Supplier<Stream<T>>.

How do I make a stream from a value that might be null?

Use Stream.ofNullable(value), added in Java 9. It returns an empty stream for null and a one-element stream otherwise. Stream.of(null value) gives a stream containing null, which tends to fail later in a mapper that calls a method on it, or in findFirst.

More examples

Dropping missing values with Stream.ofNullable

Stream.of keeps the null as an element, so the plain stream still counts 3. flatMap(Stream::ofNullable) turns each null into an empty stream, which is a tidy way to collect only the identifiers a request actually carried.

Example · java
void main() {
    String requestId = "req-42";
    String traceId = null;
    String sessionId = "s-7";

    List<String> present = Stream.of(requestId, traceId, sessionId)
        .flatMap(Stream::ofNullable)
        .toList();
    IO.println(present);

    IO.println(Stream.ofNullable(traceId).count());
    IO.println(Stream.of(requestId, traceId, sessionId).count());
}
// Output:
// [req-42, s-7]
// 0
// 3

A stream can be consumed only once

The second terminal operation on the same stream object fails. A Supplier that builds a new stream on each call is the usual fix when the same values must be processed twice.

Example · java
void main() {
    Stream<String> names = Stream.of("ada", "linus");
    IO.println(names.toList());

    try {
        names.count();
    } catch (IllegalStateException e) {
        IO.println(e.getMessage());
    }

    // Keep a way to make a fresh stream instead of the stream itself
    Supplier<Stream<String>> source = () -> Stream.of("ada", "linus");
    IO.println(source.get().count() + " " + source.get().toList());
}
// Output:
// [ada, linus]
// stream has already been operated upon or closed
// 2 [ada, linus]

Processing several lists as one

Stream.of over the lists gives a stream of three lists; flatMap(List::stream) opens each one up in order. This is how you merge users from several sources before filtering or mapping them once.

Example · java
void main() {
    List<String> admins = List.of("ada");
    List<String> editors = List.of("bob", "cyd");
    List<String> viewers = List.of("dee");

    List<String> everyone = Stream.of(admins, editors, viewers)
        .flatMap(List::stream)
        .toList();
    IO.println(everyone);

    // Without flatMap the elements are the lists themselves
    IO.println(Stream.of(admins, editors, viewers).count());

    // For exactly two streams, concat does the same job
    IO.println(Stream.concat(admins.stream(), viewers.stream()).toList());
}
// Output:
// [ada, bob, cyd, dee]
// 3
// [ada, dee]

Discussion

  • Be the first to comment on this lesson.