I have Java code which uses lambdas and streams to find the average of a list of integers. It uses Stream.reduce(...) to find the sum of integers and then calculates average. The code works correctly even when I remove the parallel() call. Can someone explain why ? More questions after the code.
import java.util.Arrays;
import java.util.List;
public class Temp {
public static void main(String [] args){
//For example, consider a list of a *series* of numbers in increasing order.
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
int n = numbers.get(numbers.size()-1);//n = 6 is the number of numbers in list.
double expectedSum = (n * (n + 1))/2;//By mathematical formula for increasing series.
Double sum = numbers
//Take a stream of integers.
.stream()
//Split the stream into mini streams and calculate sum of each of mini stream.
.parallel()
//Reduce all the numbers in a stream to their sum.
.reduce(
//start with a partial sum of 0.
0.0,
//For a stream, calculate the sum of all the numbers.
(partialSum, nextNumber) -> partialSum + (double) nextNumber,
//Add the sums of each mini stream.
(onePartialSum, anotherPartialSum) -> (onePartialSum + anotherPartialSum)
);
System.out.println("Sum : expected value = " + expectedSum + ", actual value = " + sum);
double expectedAverage = expectedSum/numbers.size();
double average = sum/numbers.size();
System.out.println("Average : expected value = " + expectedAverage + ", actual value = " + average);
}
}
Output:
Sum : expected value = 21.0, actual value = 21.0
Average : expected value = 3.5, actual value = 3.5
Consider the code below for the function which is a BinaryOperator<U> combiner
:
(onePartialSum, anotherPartialSum) -> (onePartialSum + anotherPartialSum)
How does this line actually work in parallel and non-parallel ? My understanding is that in parallel, it takes the sum of each mini stream and adds it to the "total sum". Is that correct ? When stream is not parallel, then does it do zero + totalSum of single stream ? If yes, then a more accurate replacement for the previous line of code will be (sum, onePartialSum) -> (sum + onePartialSum)
where sum is already initialized to zero ???
IN PARALLEL:
System.out.println(Arrays.asList(1, 2, 3, 4, 5).stream().parallel()
.reduce(/*identity*/1, /*accumulator*/(s, s2) -> s + s2, /*combiner*/(s, s2) -> s + s2));
OUTPUT:20
parameters to accumulator is identity and each stream value
Working:
1+1, 1+2, 1+3, 1+4, 1+5 // Output of accumulator is 2,3,4,5,6
parameters to combiner is output of accumulator as divided.
Working:
2+3 in one thread, 4+5 in another thread and then 5/*(2+3)*/+9/*(4+5)*/ and then 14/*(5+9)*/+6 = 20
IN SERIES:
System.out.println(Arrays.asList(1, 2, 3, 4, 5).stream()
.reduce(/*identity*/1, /*accumulator*/(s, s2) -> s + s2, /*combiner*/(s, s2) -> s + s2));
OUTPUT:16
In series mode, combiner won't be excuted and parameters to accumulator are identity and each stream value but result of each is set to identity
Working:
1(identity) + 1(first element) = 2(new identity)
2(new identity) + 2(second element) = 4(new identity)
4(new identity) + 3(third element) = 7(new identity)
7(new identity) + 4(third element) = 11(new identity)
11(new identity) + 5(third element) = 16(new identity)
I hope You understand.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.