5 ways to create a Stream in Java 8

Photo by Ales Krivec

Indrek Ots
by Indrek Ots
3 min read

Categories

  • articles

Tags

  • java
  • java 8
  • streams api

Notice! This post is more than a year old. It may be outdated.

Even the simplest programs use some kind of collection of elements. They are an essential part in programming. Be it arrays, lists, dictionaries or maps, they’re used to store data so it could be easily accessed and manipulated. Depending on the use case, different data structures are chosen. Arrays are good for storing a sequence of elements. Key-value data can be stored in dictionaries or maps (some programming languages call them associative arrays).

Java 8 introduced the Streams API which allows developers to declaratively manipulate collections. It promotes the usage of functional style programming. Together with lambda expressions and method references, Streams make code more concise and readable. Additionally Streams allow to pipe multiple operations one after another. If you’re familiar with Unix command-line pipes then you might find composing stream operations simple to understand. To get started with Streams, you need a method to create them. Here are five ways to create a Stream in Java 8.

Creating a Stream from a Collection

Probably the most obvious method is to create a Stream from a Collection. This is the interface that lists, sets, queues and the like implement. With the introduction of Java 8 and default methods, a method called stream() was added to the Collection interface. It returns a sequential Stream with the collection as its source. The following example shows this in action.

List<Book> library = new ArrayList<>();
library.add(new Book("Alice's Adventures in Wonderland", "Lewis Carrol"));
Stream<Book> bookStream = library.stream();

Creating a Stream from arrays

Arrays don’t have the same convenient methods that Collections have. Therefore to create a stream from an array, you need to use the static method stream() in the Arrays class. Next, you’ll see how to create a Stream of type String from an array of strings.

String[] names = {"Lewis Carrol", "H.G. Wells", "Michael Ende"};
Stream<String> stream = Arrays.stream(names);

In addition to general Streams, the Arrays class contains overloaded methods for specialized streams as well. These are streams that can be used with Java’s primitive types. Giving the stream() method an array of primitive types returns a specialized stream.

int[] integers = {1, 4, 6, 2, 6, 3, 2};
IntStream stream = Arrays.stream(integers);

Creating a Stream from values

Instead of creating an array or a collection and then converting it into a Stream, it is possible to create a Stream directly using the static method of() in the Stream interface.

Stream<String> stream = Stream.of("Lewis Carrol", "H.G. Wells", "Michael Ende");

Creating a Stream from files

Java 8 allows to create a Stream from a file. The java.nio.file.Files class contains several static methods which return a Stream of the file contents. The following example creates a Stream of Strings which represent the lines of the file.

Stream<String> lines = Files.lines(Paths.get("/tmp/data"), Charset.defaultCharset());

Alternatively, if you’re not interested in a particular file but rather in a directory in the file system, Files.list() method can create a lazily populated Stream of the elements that are the entries in the directory.

Stream<Path> list = Files.list(Paths.get("/tmp/data"));

Creating a stream from functions

Two static methods in the Stream interface allow you to create infinite Streams. Yes, that’s right. Unlike a Collection or an array, a Stream can have no bounds. The methods we’re going to look at are iterate() and generate().

Iterate

Iterate accepts an initial element and a function which is applied to the previous element to produce the next element. The following example produces an infinite Stream of even numbers.

Stream<Integer> evenNumbers = Stream.iterate(0, n -> n + 2);

A lambda expression of type UnaryOperator is used to produce the next even number by adding 2 to the previous number.

Generate

Generate accepts a Supplier to generate an infinite Stream of unsorted elements. This method is good for generating a Stream of random elements as can be seen in the following example.

Stream<Double> randomNumbers = Stream.generate(Math::random);

Conclusion

Learning the Streams API will help you to express complex ideas succinctly. The first step to getting started is creating a new stream object. We covered several methods of stream creation. In future articles we’ll dive deeper into stream operations.