Using java streams to find if a number is prime or not

亡梦爱人 提交于 2020-01-03 04:53:07

问题


I am reading Cracking the Coding Interview and it has an example of finding prime number which I ran on JShell

boolean isPrime(int n) {
  for (int i = 2; i * i <= n; i++) {
    if (n % i == 0) {
      return false;
    }
  }
  return true;
}

then I am trying to convert this to streams in java, but finding this difficult as mentioned

boolean isPrimeStream(int n) {
  return IntStream.range(0, n) // how to do similar to for loop above
    .anyMatch(i -> n % i == 0);  // i think this is the reason for failure
}

回答1:


Problem one, you should be using noneMatch (not anyMatch). Problem two, your range is off. Use rangeClosed (or add one to your end) which should be the square root of n (not just n) - and you started with 2 as an initial value in your first test. Also, you might as well make the method static. Like,

static boolean isPrimeStream(int n) {
    return IntStream.rangeClosed(2, (int) Math.sqrt(n)) 
            .noneMatch(i -> n % i == 0);
}

Also, we can improve your first example by handling 2 as a special case. That allows you to begin with three and increment by two skipping all even values.

static boolean isPrime(int n) {
    if (n == 2) {
        return true;
    } else if (n % 2 == 0) {
        return false;
    }
    for (int i = 3; i * i <= n; i += 2) {
        if (n % i == 0) {
            return false;
        }
    }
    return true;
}



回答2:


You should use IntStream.noneMatch there as:

boolean isPrimeStream(int n) {
    return IntStream.range(2, n) // note  division by zero possible in your attempt
                    .noneMatch(i -> n % i == 0);
}

Edit: As pointed in comments by Andreas, using range(2, n) to avoid division by zero and since division by 1 would always lead to the condition being true and returning the result as false otherwise.

Returns whether no elements of this stream match the provided predicate

Your current code is using IntStream.anyMatch

Returns whether any elements of this stream match the provided predicate

which is why it would return true if the condition specified is satisfied for any input instead of when the method is supposed to return false.


how to do similar to for loop above

With java-9 or above you could use IntStrem.iterate as

private boolean isPrimeStream(int n) {
    return IntStream.iterate(2, i -> i * i <= n, i -> i + 1) // similar to the loop
                    .noneMatch(i -> n % i == 0);
}



回答3:


What is the point of using Java8 streams to get this thing done. To me you are reinventing the wheel. This one liner will be suffice.

BigInteger.valueOf(n).isProbablePrime(50);

Also notice that there are some problems which can be better solved using streams. But that does not mean stream is the silver bullet to solve all your problems.

Here's an excerpt from the Documentation about certainty.

For a large known prime, and for any certainty > 0, is it accurate to say that b.isProbablePrime(certainty) will always return true.



来源:https://stackoverflow.com/questions/53905935/using-java-streams-to-find-if-a-number-is-prime-or-not

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!