Search code examples
java-8java-streamside-effects

Side-effects in java 8 streams


There are several things in Oracle docs that I cannot fully understand:

Operations like forEach and peek are designed for side effects;

What they mean by "designed"? What is so special about those two? I can write my code so that any stream API method works via side effect. It's completely up to me, as far as I can understand. What's more, I would usually use peek() to modify the state of the element, not the source itself, which doesn't make it stateful or side-effect-prone.

The javadoc for forEach also says:

The behavior of this operation is explicitly nondeterministic.

I understand it when they say the same thing about findAny, but what's non-deterministic about forEach? Any operation in parallel stream cannot guarantee ordering if the stream is not ordered. Why is nondeterminism only mentioned for forEach(and finAny, but it means a bit different thing)?

For peek and forEach javadoc also contains:

action may be performed at whatever time and in whatever thread the library chooses

Again, why only there? Why isn't it mentioned for the rest of the operations?


Solution

  • First, modifying an object state is also a side-effect as the overall state of your program changes after executing your lambda. You can even have a concurrency problem here if you have the same object several times in your parallel stream. Side-effect-free function is a function which does not change the program state and its return value is based only on its arguments. As other stream operations are required to be side-effect-free, it's unnecessary to mention in which thread and at which time they will be executed as this should not matter. But if operation is allowed to have side-effect, this should be mentioned explicitly.

    The forEach differs from forEachOrdered even if the stream is unordered: forEachOrdered always guarantees that its lambda is not executed concurrently in several different threads at a time. The forEach call not only makes your stream implicitly unordered, but also removes this guarantee: your lambda can be executed concurrently now. And as lambda may produce side-effect, this should be mentioned explicitly.