An identity element is a value that leaves an operand unchanged under an operation. For Stream.reduce(identity, accumulator), the identity must work on either side: x ⊕ i = x and i ⊕ x = x. The accumulator must also be associative. section 9.5
A sequential stream can hide a broken identity
A List.hashCode() calculation can appear correct with reduce(1, (x, y) -> x * 31 + y), even though 1 is not an identity: applying the accumulator to (1, 10) produces 41, not 10. Sequential evaluation may conceal the contract violation; parallel evaluation can produce a wrong result because computation order changes. section 9.5
List<String> list = List.of("a", "b", "c", "d");
System.out.println(list.hashCode()); #1
System.out.println(list.stream()
.mapToInt(Objects::hashCode)
.reduce(1, (x, y) -> x * 31 + y)); #2
Compare the ordinary List.hashCode() result with the Stream.reduce implementation that appears correct sequentially but violates the identity and associativity requirements. section 9.5
Avoid this failure mode by:
- Choosing an identity and accumulator that satisfy both identity laws and associativity before using reduce. section 9.5
- Testing with parallelStream(), because code that works sequentially may fail when reduction order changes. section 9.5




