Java 8 Stream generate() Method


In this article, we will explore the generate() method provided by Java 8 Stream API. The generate() method is a factory method introduced in the java.util.stream.Stream class. It generates an infinite stream of elements based on a provided supplier function.

The method signature is as follows:

static <T> Stream<T> generate(Supplier<T> s)

Here, the Supplier<T> is a functional interface that represents a supplier of values. It has a single abstract method T get(), which produces and returns a value of type T. The generate() method repeatedly calls the get() method of the supplier to create a stream of elements.

1. Creating Infinite Streams

One of the most compelling use cases for the generate() method is the creation of infinite streams. These are streams that can potentially contain an endless number of elements. While this might sound counterintuitive, it becomes extremely powerful when combined with other Stream API methods like limit().

Let’s take a look at a simple example where we generate an infinite stream of random integers using the generate() method:

StreamGenerateExample.java
package org.websparrow;

import java.util.Random;
import java.util.stream.Stream;

public class StreamGenerateExample {
    public static void main(String[] args) {
        Random random = new Random();

        Stream<Integer> randomIntStream = Stream.generate(random::nextInt);

        randomIntStream
            .limit(20) // Limit the stream to 20 elements
            .forEach(System.out::println);
    }
}

Output (output may vary on each run):

console.log
-1234567890
987654321
...

In this example, we create an infinite stream of random integers using the generate() method and the nextInt() method of the Random class. By applying the limit(20) operation, we restrict the stream to contain only the first 20 generated random integers. Finally, the forEach() terminal operation prints each element.

2. Dynamic Element Generation

The generate() method can also be used to dynamically generate elements based on some logic. This is particularly useful when you need to create a stream of elements that are computed on-the-fly. Let’s consider a scenario where we generate a stream of Fibonacci numbers using the generate() method:

FibonacciStreamExample.java
package org.websparrow;

import java.util.function.Supplier;
import java.util.stream.Stream;

public class FibonacciStreamExample {
    public static void main(String[] args) {
        Stream<Long> fibonacciStream = Stream.generate(new FibonacciSupplier());

        fibonacciStream
            .limit(10)
            .forEach(System.out::println);
    }
}

class FibonacciSupplier implements Supplier<Long> {
    private long previous = 0;
    private long current = 1;

    @Override
    public Long get() {
        long next = previous + current;
        previous = current;
        current = next;
        return previous;
    }
}

Output:

console.log
1
1
2
3
5
8
13
21
34
55

Here, we define a custom FibonacciSupplier class that implements the Supplier<Long> interface. The get() method of this supplier generates the next Fibonacci number in the sequence. By using this supplier with the generate() method, we create a stream of Fibonacci numbers.

References

  1. Java Stream map() vs flatMap() Method
  2. Java 8 Stream filter() Method Example
  3. generate(Supplier<T> s) – JavaDoc

Similar Posts

About the Author

Atul Rai
I love sharing my experiments and ideas with everyone by writing articles on the latest technological trends. Read all published posts by Atul Rai.