Supplier is a functional interface that defines a method called get() that returns an instance of a certain type without taking any arguments. The Supplier interface is commonly used to generate streams using the Stream.generate method.

Here’s an example of using a Supplier to generate an infinite stream of random numbers in Java:

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

In this example, Math::random is a method reference to the random method of the Math class, which returns a random double value between 0 and 1. The Stream.generate method takes a Supplier as an argument, and creates a new stream that generates an infinite sequence of random numbers by repeatedly calling the get() method on the random supplier.

You can also use the Stream.generate method in combination with limit to generate a finite stream:

Supplier<Integer> ints = new Random()::nextInt;
Stream<Integer> finiteRandomNumbers = Stream.generate(ints).limit(10);

This will give you a stream of 10 random integers. It’s also worth noting that you can create your own supplier by implementing the Supplier interface and providing an implementation for the get() method.

In summary, a Supplier is a functional interface that is used to generate streams by providing a way to generate elements for the stream. The Stream.generate method is used to create a new stream that generates an infinite sequence of elements by repeatedly calling the get() method on the provided Supplier.

Supplier Code Examples:

  1. Generating a stream of random alphabets:
Supplier<Character> alphabets = () -> (char)('a' + Math.random() * ('z' - 'a' + 1));
Stream<Character> randomAlphabets = Stream.generate(alphabets);
  1. Generating a stream of fibonacci numbers:
Supplier<Integer> fibonacci = new FibonacciSupplier();
Stream<Integer> fibonacciNumbers = Stream.generate(fibonacci);

Where the class FibonacciSupplier is defined as:

class FibonacciSupplier implements Supplier<Integer> {
    private int previous = 0;
    private int current = 1;

    @Override
    public Integer get() {
        int nextValue = previous + current;
        previous = current;
        current = nextValue;
        return current;
    }
}
  1. Generating a stream of prime numbers:
Supplier<Integer> primes = new PrimeSupplier();
Stream<Integer> primeNumbers = Stream.generate(primes);

Where the class PrimeSupplier is defined as:

class PrimeSupplier implements Supplier<Integer> {
    private int current = 2;

    @Override
    public Integer get() {
        while(!isPrime(current)) {
            current++;
        }
        return current++;
    }

    private boolean isPrime(int number) {
        // check if the number is prime
    }
}

It’s worth noting that these examples generate an infinite stream, so it’s important to use the limit method to limit the size of the stream if needed.

As you can see, the Supplier can be a simple function as the random one or a more complex one like the FibonacciSupplier or PrimeSupplier where you can use it to generate a specific sequence of elements.