StreamAPI版エラトステネスの篩
ラボでプログラミング課題で三回生が素数判定をMPIだのCUDAだので実装していたのですが、そういえばStreamAPIでエラトステネスの篩が書けない〜っていうブログがいくつかあったのを思い出しました。
forやifで書くアレをStream APIで書く - Java EE 事始め!
ゆっちのBlog » Java8 時代の素数の求め方
雰囲気エラトステネスの篩をStreamAPI+再帰で書いてみました。全然遅延実行されないので糞っぽい。
/* package whatever; // don't place package name! */ import java.util.*; import java.lang.*; import java.io.*; import java.util.stream.*; /* Name of the class has to be "Main" only if the class is public. */ class Ideone { public static void main (String[] args) throws java.lang.Exception { primeStream(100).forEach(System.out::println); } public static IntStream primeStream(int max) { return primes(IntStream.range(2, max)); } private static IntStream primes(IntStream stream) { PrimitiveIterator.OfInt i = stream.iterator(); if (!i.hasNext()) {return IntStream.empty();} int p = i.next(); IntStream rest = stream(i); return IntStream.concat(IntStream.of(p), primes(rest.filter(n -> n % p != 0))); } private static IntStream stream(PrimitiveIterator.OfInt i) { return StreamSupport.intStream(Spliterators.spliteratorUnknownSize(i, 0), false); } }
ポイントはStream#findFirstで最初の値を取りだすと残りのデータが使えなくなってしまうけど、Stream#iteratorでIteratorを取ってくると、残りのデータも使えるという点ですね。
IteratorからStreamに戻すためには、Spliterators#spliteratorXxxでSpliteratorを取ってきて、それをStreamSupport#streamに渡せばよいです。