Java Reference
In-Depth Information
Unfortunately, we're still left in a situation where our code has two responsibilities. For the
most part, our code here is dealing with looping over numbers. If we follow the single re-
sponsibility principle, then iteration should be encapsulated elsewhere. There's also a good
practical reason to improve this code. If we want to count the number of primes for a very
large
upTo
value, then we want to be able to perform this operation in parallel. That's
right—the threading model is a responsibility of the code!
We can refactor our code to use the Java 8 streams library (see
Example 8-36
)
, which deleg-
ates the responsibility for controlling the loop to the library itself. Here we use the
range
method to count the numbers between
0
and
upTo
,
filter
them to check that they really are
prime, and then
count
the result.
Example 8-36. Refactoring the prime checking to use streams
public
public
long
long
countPrimes
(
int
int
upTo
) {
return
return
IntStream
.
range
(
1
,
upTo
)
.
filter
(
this
this
::
isPrime
)
.
count
();
}
private
private
boolean
boolean
isPrime
(
int
int
number
) {
return
return
IntStream
.
range
(
2
,
number
)
.
allMatch
(
x
-> (
number
%
x
) !=
0
);
}
If we want to speed up the time it takes to perform this operation at the expense of using
more CPU resources, we can use the
parallelStream
method without changing any of the
other code (see
Example 8-37
).
Example 8-37. The streams-based prime checking running in parallel
public
public
long
long
countPrimes
(
int
int
upTo
) {
return
return
IntStream
.
range
(
1
,
upTo
)
.
parallel
()
.
filter
(
this
this
::
isPrime
)
.
count
();
}
private
private
boolean
boolean
isPrime
(
int
int
number
) {
return
return
IntStream
.
range
(
2
,
number
)
.
allMatch
(
x
-> (
number
%
x
) !=
0
);
}