微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Java 8:流和Eratosthenes的Sieve

Eratosthenes的Sieve可以在Haskell中非常巧妙地实现,使用懒惰生成无限列表,然后从尾部删除列表头部的所有倍数:

primes :: [Int]
primes = sieve [2..]
sieve (x:xs) = x : sieve [y | y <- xs,y `mod` x > 0]

我正在尝试学习如何在Java 8中使用流,但我想出是否有一种方法可以在Java中实现与上面的Haskell代码相同的结果.如果我将Haskell惰性列表视为等同于Java流,似乎我需要使用以2为首的流并生成一个删除了所有2的倍数的新流,然后获取该流并生成所有流的新流删除3的倍数,并…

我不知道如何继续.

有没有办法做到这一点,或者当我试图将Java流视为与Haskell列表相当时,我是在欺骗自己?

最佳答案
当然,有可能,但由于Java流没有简单的方法被分解到它们的头部和它们的尾部(你可以很容易地获得其中任何一个,但不是两个都可以,因为流已经被消费了然后 – 听起来有人可以使用线性类型……).

解决方案是保持可变变量.例如,该可变变量可以是测试数字是否是目前为止看到的任何其他数字的倍数的谓词.

import java.util.stream.*;
import java.util.function.IntPredicate;

public class Primes {

   static IntPredicate isPrime = x -> true;
   static IntStream primes = IntStream
                               .iterate(2,i -> i + 1)
                               .filter(i -> isPrime.test(i))
                               .peek(i -> isPrime = isPrime.and(v -> v % i != 0));

   public static void main(String[] args) {
      // Print out the first 10 primes.
      primes.limit(10)
            .forEach(p -> System.out.println(p));

   }
}

然后,您得到预期的结果:

$javac Primes.java
$java Primes
2
3
5
7
11
13
17
19
23
29

原文地址:https://www.jb51.cc/java/438284.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐