Reputation: 1
I'm trying to create an infinite IntStream of prime number, and it must be fast - produce about a million primes in few seconds.So I try to create the stream generated with filter recall IntStream itself:
IntStream primeStream = IntStream.iterate(2, n -> n + 1)
.filter(PrimeStream::isPrime);
with isPrime like this:
public boolean isPrime(int n, IntStream primeStream) {
primeStream.forEach((p) -> {
if (n % p == 0)
return false;
if (p > Math.sqrt(n))
break;
});
return true;
}
Then is that possible? Or is there other way working with Stream to finish my task?
Upvotes: 0
Views: 157
Reputation: 159165
The entire point of an infinite IntStream
, is that it consumes no memory, i.e. it doesn't "remember" streamed values. It just produces new int
values.
If you need to remember values, you need to do it yourself.
I'd suggest using IntStream.generate(IntSupplier s)
, with an IntSupplier
that remembers previously generated prime numbers.
public final class PrimeGenerator implements IntSupplier {
private final List<Integer> primes = new ArrayList<>();
@Override
public int getAsInt() {
int prime;
final int count = this.primes.size();
if (count == 0)
prime = 2;
else if (count == 1)
prime = 3;
else {
prime = this.primes.get(count - 1) + 2;
while (! isPrime(prime))
prime += 2;
}
this.primes.add(prime);
return prime;
}
private boolean isPrime(int n) {
for (int p : this.primes) {
if (n % p == 0)
return false;
if (p * p > n)
return true;
}
return true;
}
}
Using that like this:
long start = System.nanoTime();
System.out.println(IntStream.generate(new PrimeGenerator()).limit(1000000).max().getAsInt());
long stop = System.nanoTime();
System.out.println("Elapsed: " + (stop - start) / 1000000000d + " seconds");
will show the 1 millionth prime number:
15485863
Elapsed: 1.749469734 seconds
Upvotes: 5