Other answers suggested that the approach I tried was not possible and that a separate collection needs to be used.
To provide a more complete answer, I would like to provide a valid approach to this problem using threads and compare it with a more traditional approach.
Listing of primes using streams (using a sieve of eratosthenes):
List<Integer> primes = new ArrayList<Integer>(); IntStream.iterate(2, i -> i + 1) .limit(UPPER_BOUND) .filter(i -> { for(int j=0; j<primes.size(); j++) { int prime = primes.get(j); if(prime > Math.sqrt(i)) { break; } if(i % prime == 0) { return false; } } return true; }) .forEach(primes::add);
The traditional, equivalent, threadless approach:
List<Integer> primes = new ArrayList<Integer>(); for(int i=2; i < UPPER_BOUND; i++) { boolean isPrime = true; for(int j=0; j<primes.size(); j++) { int prime = primes.get(j); if(prime > Math.sqrt(i)) { break; } if(i % prime == 0) { isPrime = false; break; } } if(isPrime) { primes.add(i); } }
Performance Comparison:
Some experiments with each function have consistently demonstrated that the traditional approach is actually faster than using threads in this case. The thread approach was sequentially performed 1.5 times longer in order to find all primes less than one million compared to the traditional approach (on average 106 ms and 70 ms, respectively, on my machine).
This performance difference can probably be easily implemented if the stream.parallel () function can easily parallelize the problem. However, in this case, parallelization is not easy, since ArrayList is not thread safe and quickly leads to errors and / or inaccurate results.
Output:
Assuming the other answers are correct, filtering already filtered data inside the filter in the same stream is not possible in Java.
Listing primes can be resolved using streams. However, expecting a better solution than my own, itโs better to stick to the traditional, unrated approach now.
Porthos3
source share