Java Streams - Java Stream From Functions








We can have a function that can generate values on demand.

The following two static methods from Stream interface generates an infinite stream from a function.

<T> Stream<T> iterate(T  seed, UnaryOperator<T>  f)
<T> Stream<T> generate(Supplier<T> s)

iterate() method creates a sequential ordered stream.

generate() method creates a sequential unordered stream.

IntStream, LongStream, and DoubleStream contain iterate() and generate() methods that take parameters specific to their primitive types and generate values.

For example, the following two methods are defined in the IntStream interface:

IntStream iterate(int seed,  IntUnaryOperator f)
IntStream generate(IntSupplier s)




Stream.iterate()

The iterate() method takes two arguments: a seed and a function.

A seed is the first element of the stream. The second element is generated by applying the function to the first element. The third element is generated by applying the function on the second element.

Therefore the elements are: seed, f(seed), f(f(seed)), f(f(f(seed)))....

The following code creates a stream of natural numbers:

Stream<Long> naturalNumbers = Stream.iterate(1L, n -> n + 1);

The limit(long maxSize) operation is an intermediate operation that produces another stream.

The following code creates a stream of the first 10 natural numbers:

import java.util.stream.Stream;
//  w ww.  jav  a  2s  .c  o  m
public class Main {
  public static void main(String[] args) {
    Stream<Long> tenNaturalNumbers = Stream.iterate(1L, n  ->  n  + 1)
        .limit(10);

    tenNaturalNumbers.forEach(System.out::println);
  }
}

The code above generates the following result.





Example 2

The following code filters the values generated from an iterate function.

import java.util.stream.Stream;
//from w w w  . j a v a2 s  .c  om
public class Main {
  public static void main(String[] args) {
    Stream.iterate(2L, n  ->  n  + 1)
    .filter(Main::isOdd)
    .limit(5)
    .forEach(System.out::println);
  }
  public static boolean isOdd(long number) {
    if (number % 2 == 0) {
      return false;
    }
    return true;
  }
}

The code above generates the following result.

Example 3

To discard some elements from a stream, use the skip operation.

The skip(long n), an intermediate operation, skips the first n elements of the stream.

The following code uses skip to skip the first 100 odd number:

import java.util.stream.Stream;
/*from   ww  w .j a v a 2s. com*/
public class Main {
  public static void main(String[] args) {
    Stream.iterate(2L, n  ->  n  + 1)
    .filter(Main::isOdd)
    .skip(100)
    .limit(5)
    .forEach(System.out::println);
  }
  public static boolean isOdd(long number) {
    if (number % 2 == 0) {
      return false;
    }
    return true;
  }
}

The code above generates the following result.

Stream.generate()

generate(Supplier<T> s) uses Supplier to generate an infinite sequential unordered stream.

Example

The following code prints five random numbers.

import java.util.stream.Stream;
/*  ww w  .ja  v  a 2s  . c  om*/
public class Main {
  public static void main(String[] args) {
    Stream.generate(Math::random)
    .limit(5)
    .forEach(System.out::println);

  }
}

The code above generates the following result.

Example 4

To generate a stream in which the next element is generated based on the previous one, you will need to use a Supplier that stores the last generated element.

The following code keeps the last value in a static variable.

import java.util.stream.Stream;
/*  www  .  j a v a  2 s .c om*/
public class Main {
  public static void main(String[] args) {
    Stream.generate(Main::next)
    .limit(5)
    .forEach(System.out::println);

  }
  
  static int i=0;
  private static int next(){
    i++;
    return i;
  }
}

The code above generates the following result.

Random Stream

java.util.Random class provides ints(), longs(), and doubles() return infinite IntStream, LongStream, and DoubleStream, respectively.

The following code prints five random int values from an IntStream returned from the ints() method of the Random class:

import java.util.Random;
/* ww  w .  j  a v a 2  s  . c o m*/
public class Main {
  public static void main(String[] args) {
    new Random().ints()
    .limit(5)
    .forEach(System.out::println);

  }
}

The code above generates the following result.

Example 5

We can use the nextInt() method of the Random class as the Supplier in the generate() method to achieve the same.

import java.util.Random;
import java.util.stream.Stream;
/*from   w  w w . jav a 2 s  .  c  o  m*/
public class Main {
  public static void main(String[] args) {
    Stream.generate(new Random()::nextInt)
    .limit(5)
    .forEach(System.out::println);
  }
}

The code above generates the following result.

Example 6

To work with only primitive values, use the generate() method of the primitive type stream interfaces.

import java.util.Random;
import java.util.stream.IntStream;
//from  w  ww . j  a  v a2s  .co  m
public class Main {
  public static void main(String[] args) {
    IntStream.generate(new Random()::nextInt)
    .limit(5)
    .forEach(System.out::println);

  }
}

The code above generates the following result.

Example 7

To generate an infinite stream of a repeating value.

import java.util.stream.IntStream;

public class Main {
  public static void main(String[] args) {
    IntStream.generate(() ->  0)
    .limit(5)
    .forEach(System.out::println);
  }
}

The code above generates the following result.