5

How I can replace this code with new Java Stream API:

int n = someFunction();    // n > 0
for (int i = 3; i * i <= n; i += 2)
    System.out.print(i);

I have tried to using IntStream.iterate(3, i -> i + 2), but I can't add stop condition.

As I understand I can't use .limit(int) method here.

Any ideas?

Tunaki
  • 132,869
  • 46
  • 340
  • 423
Dub Nazar
  • 522
  • 6
  • 12

2 Answers2

5

You could use limit(int): you would have to determine how many elements are going to be between 3 and sqrt(n) by steps of 2. There are exactly (sqrt(n) - 3) / 2 + 1 elements, so you could write:

IntStream.iterate(3, i -> i + 2).limit((int) (Math.sqrt(n) - 3) / 2 + 1);

Having said that, you could also create a closed range from 3 to sqrt(n) and filter out the even values, like this:

IntStream.rangeClosed(3, (int) Math.sqrt(n)).filter(i -> i % 2 > 0)
Tunaki
  • 132,869
  • 46
  • 340
  • 423
  • 2
    Apparently this problem will be solved in Java 9:http://stackoverflow.com/questions/20746429/limit-a-stream-by-a-predicate – Paul Boddington Oct 25 '15 at 12:50
  • 2
    The range version will also give you much better parallel behavior (for two reasons; parallel limit is expensive, and iterate() is a fundamentally sequential way to generate a stream source.) – Brian Goetz Oct 25 '15 at 18:24
3

Using my free StreamEx library two more solutions are possible in addition to ones proposed in @Tunaki answer.

  1. Using backport of takeWhile method which appears in JDK-9:

    IntStream is = IntStreamEx.iterate(3, i -> i + 2).takeWhile(i -> i*i <= n);
    
  2. Using three-argument IntStreamEx.rangeClosed which allows to specify the step:

    IntStream is = IntStreamEx.rangeClosed(3, (int) Math.sqrt(n), 2);
    
Tagir Valeev
  • 97,161
  • 19
  • 222
  • 334