Java Reference
In-Depth Information
for
for
(
int
int
i
=
0
;
i
<
values
.
length
;
i
++) {
values
[
i
] =
i
;
}
return
return
values
;
}
We can use the
parallelSetAll
method in order to do this easily in parallel. An example of
this code is shown in
Example 6-8
. We provide an array to operate on and a lambda expres-
sion, which calculates the value given the index. In our example they are the same value.
One thing to note about these methods is that they alter the array that is passed into the oper-
ation, rather than creating a new copy.
Example 6-8. Initializing an array using a parallel array operation
public
public static
static
double
double
[]
parallelInitialize
(
int
int
size
) {
double
double
[]
values
=
new
double
[
size
];
Arrays
.
parallelSetAll
(
values
,
i
->
i
);
return
new
double
return
values
;
}
The
parallelPrefix
operation, on the other hand, is much more useful for performing
accumulation-type calculations over time series of data. It mutates an array, replacing each
element with the
sum
of that element and its predecessors. I use the term “sum” loosely—it
doesn't need to be addition; it could be any
BinaryOperator
.
An example operation that can be calculated by prefix sums is a simple moving average.
This takes a rolling window over a time series and produces an average for each instance of
that window. For example, if our series of input data is
0, 1, 2, 3, 4, 3.5
, then the
prefix sum in order to calculate a moving average.
Example 6-9. Calculating a simple moving average
public
public static
static
double
double
[]
simpleMovingAverage
(
double
double
[]
values
,
int
int
n
) {
double
double
[]
sums
=
Arrays
.
copyOf
(
values
,
values
.
length
);
Arrays
.
parallelPrefix
(
sums
,
Double:
:
sum
);
int
int
start
=
n
-
1
;
return
return
IntStream
.
range
(
start
,
sums
.
length
)
.
mapToDouble
(
i
-> {
double
double
prefix
=
i
==
start
?
0
:
sums
[
i
-
n
];
return
return
(
sums
[
i
] -
prefix
) /
n
;
})
.
toArray
();
}