【发布时间】:2019-02-18 00:03:03
【问题描述】:
我编写了以下代码来获取 2..n 中的所有素数
private static LongStream getPrimesStream(long number) {
return LongStream.range(2, number + 1)
.filter(PrimeStreamTest::isPrime);
}
private static boolean isPrime(final long number) {
return number == 2 || (number % 2 != 0 && LongStream
.range(2, (long) Math.ceil(Math.sqrt(number + 1)))
.filter(n -> n % 2 != 0)
.noneMatch(divisor -> number % divisor == 0)
);
}
我通过检查 2..sqrt(n) 的范围并过滤掉偶数来优化它,但现在我想通过存储所有以前找到的素数来进一步优化它(我不关心内存),这样我就可以过滤掉可被这些素数整除的数字,而不仅仅是可被 2 整除的数字。 我知道有更好的解决方案,但这只是对 lambda 和流的练习。
【问题讨论】:
-
我相信更好的优化是 (a) 从 noneMatch() 更改为 anyMatch() 并否定结果 (b) 您拥有的过滤操作实际上非常仅限于检查2..sqrt(input) 之间的范围可被 2 整除,并且不检查其他素数,如 3,5.... 而不是所有这些步骤,只要数字可被 2,3 整除,流就会返回,4,5,....
-
@Baski:您为什么认为从
noneMatch()更改为anyMatch()并否定结果会优化任何东西? -
如果您想以内存为代价优化速度,请使用
BitSet实现 Eratosthenes 筛。但是,由于这是流中的练习,您可以在isPrime中使用getPrimesStream来获取要测试的主要因素:return number == 2 || getPrimesStream((long) ceil(sqrt(number))).noneMatch(divisor -> number % divisor == 0); -
@Misha:在这种情况下,如果
isPrime测试0和1(或简单地<2)并在启动不必要的流操作之前拒绝它们,它可能有助于性能. -
@Holger 感谢您发现错误信息。我猜我被困在了精神障碍上,没有完全阅读 API 文档。
标签: lambda java-8 java-stream