T reduce(T identity,
BinaryOperator<T> accumulator)
//(T, T) -> T
The identity value is “accumulated” with every T values
T result = identity;
for (T element : this stream)
result = accumulator.apply(result, element)
return result;
<U> U reduce(U identity,
BiFunction<U,? super T,U> accumulator,
//(U, T) -> U
BinaryOperator<U> combiner)
//(U, U) -> U
The combiner combines the multiple intermediate results of type U into a single result of type U
The intermediate values are of type U instead of type T because we have N threads reduce the T values in its segment into N intermediate values of type U.