【问题标题】:Using java streams to find if a number is prime or not使用java流来查找一个数字是否是素数
【发布时间】:2025-12-09 05:05:02
【问题描述】:

我正在阅读 Cracking the Coding Interview,它有一个我在 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
}

【问题讨论】:

    标签: java java-stream primes


    【解决方案1】:

    你应该在那里使用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 在 cmets 中指出的那样,使用 range(2, n) 来避免被零除,因为除以 1 总是会导致条件为真并返回否则结果为false

    返回此流的 没有元素 是否与提供的匹配 谓词

    您当前的代码使用的是IntStream.anyMatch

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

    这就是为什么如果任何输入都满足指定的条件而不是该方法应该返回false时它会返回true


    类似上面的for循环怎么做

    或以上可以使用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);
    }
    

    【讨论】:

      【解决方案2】:

      问题一,您应该使用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 == 1 || n % 2 == 0) {
              return false;
          }
          for (int i = 3; i * i <= n; i += 2) {
              if (n % i == 0) {
                  return false;
              }
          }
          return true;
      }
      

      【讨论】:

        【解决方案3】:

        使用 Java8 流来完成这件事有什么意义。对我来说,你正在重新发明*。这一个班轮就足够了。

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

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

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

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

        【讨论】: