3

I want to iterate / generate an infinite IntStream or LongStream and limit them by a provided max value, and not by the count of elements which is posible with the operation limit(long n), for example to get the first 20 positive even numbers:

List<Integer> evens = IntStream.iterate(0, i -> i + 2)
                               .limit(20)
                               .boxed()
                               .collect(Collectors.toList());

What I need is to limit the stream by a max value. If for example I need all powers of two under 1000

List<Integer> evens = IntStream.iterate(1, i -> i * 2)  //1, 2, 4, 8, 16, 32...
                               .limit(<here some how use the value 1000>)
                               .boxed()
                               .collect(Collectors.toList());

or Fibonacci sequence

List<Long> fibs = Stream.iterate(new long[]{1,1}, f -> new long[]{f[1], f[0] + f[1]})  //1,1,2,3,5,8,13,21...
                        .mapToLong(f -> f[1])
                        .limit(i -> i < 1000) //I know this doesn't work as limit expects a long value
                        .boxed()
                        .collect(Collectors.toList()); 

Filter doesn't work and leads to OutOfMemoryError

List<Integer> evens = IntStream.iterate(1, i -> i * 2)  //1, 2, 4, 8, 16, 32...
                               .filter(i -> i <= 1000)
                               .boxed()
                               .collect(Collectors.toList());

I have many different UnaryOperators which I want to use to generate different sequences of numbers (not only the simple examples I gave above, like i -> i * 2 where i could somehow calculate the possible count of the elements in a given range).

Question: how can I limit the stream by a given max value instaed of count of elements?

wannaBeDev
  • 516
  • 3
  • 14

3 Answers3

10

In Java 9+, use takeWhile(i -> i <= value).

Louis Wasserman
  • 191,574
  • 25
  • 345
  • 413
6

You are looking for takeWhile

List<Integer> evens = IntStream.iterate(1, i -> i * 2)  //1, 2, 4, 8, 16, 32...
                               .takeWhile(i -> i <= 1000)
                               .boxed()
                               .collect(Collectors.toList());
adnan_e
  • 1,764
  • 2
  • 16
  • 25
5

In all your shown cases, you didn't use the iterate()'s method that allowed a conditional. So if someone is still not not up to Java 9, it can be done like this:

  • Get the even values up to and including 20.
List<Integer> evens = IntStream.iterate(0, i->i<=20, i->i+2)
    .boxed()
    .collect(Collectors.toList());

System.out.println(evens);
  • get fibonacci series less than 100
List<Long> fibs = Stream.iterate(new long[]{1,1}, f->f[1] < 100,f -> new long[] 
               {f[1], f[0] + f[1]})
     .mapToLong(f -> f[1])
     .boxed()
     .collect(Collectors.toList());

System.out.println(fibs);
  • get the powers of 2 up to and including 128.
List<Integer> powersOfTwo = IntStream.iterate(1, i-> i <= 128, i -> i * 2)  //1, 2, 4, 8, 16, 32...
        .boxed()
        .collect(Collectors.toList());
    
System.out.println(powersOfTwo);

Prints

[0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
[1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
[1, 2, 4, 8, 16, 32, 64, 128]
WJS
  • 36,363
  • 4
  • 24
  • 39