使用Java流查找数字是否为质数

时间:2018-12-23 18:02:08

标签: java java-stream primes

我正在阅读破解编码面试,其中有一个示例,该示例可以找到我在JShell上运行的素数

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

然后我试图将其转换为java中的流,但是发现存在上述困难

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
}

3 个答案:

答案 0 :(得分:4)

问题一,您应该使用noneMatch(而不是anyMatch)。问题二,您的范围不对。使用rangeClosed(或在末尾添加一个),该值应为n的平方根(而不仅仅是n)-在第一个测试中,您以2作为初始值。另外,您也可以使用方法static。喜欢,

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

此外,我们可以通过处理2作为特例来改进您的第一个示例。这样一来,您可以从3开始,然后以2为增量,跳过所有偶数值。

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;
}

答案 1 :(得分:3)

您应该在此处使用IntStream.noneMatch

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

编辑 :正如Andreas的评论所指出的那样,使用range(2, n)避免被零除,因为除以1总是会导致条件为真并返回否则为false的结果。

  

返回此流的 无元素 是否与提供的   谓词

您当前的代码正在使用IntStream.anyMatch

  

返回此流的 任何元素 是否与提供的   谓词

这就是为什么如果任何输入都满足指定条件的情况,而不是方法应返回true的情况下,它将返回false的原因。


  

与上面的for循环类似的操作方式

使用或更高版本,您可以将IntStrem.iterate用作

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);
}

答案 2 :(得分:2)

使用Java8流完成此任务的意义是什么?对我而言,您正在重新发明轮子。这一条衬里就足够了。

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

还要注意,使用流可以更好地解决一些问题。但这并不意味着流是解决所有问题的灵丹妙药。

这是文档中有关确定性的摘录。

  

对于一个大的已知质数,并且对于> 0的任何确定性,   说b.isProbablePrime(certainty)将始终返回true。