Java 8 Java8流中的副作用

Java 8 Java8流中的副作用,java-8,java-stream,side-effects,Java 8,Java Stream,Side Effects,Oracle文档中有几点我无法完全理解: Operations like forEach and peek are designed for side effects; “设计”是什么意思?这两个人有什么特别之处?我可以编写代码,这样任何流API方法都可以通过副作用工作。据我所知,这完全取决于我。此外,我通常会使用peek()来修改元素的状态,而不是源代码本身,这不会使它有状态或容易产生副作用 forEach的javadoc还说: The behavior of this operation

Oracle文档中有几点我无法完全理解:

Operations like forEach and peek are designed for side effects;
“设计”是什么意思?这两个人有什么特别之处?我可以编写代码,这样任何流API方法都可以通过副作用工作。据我所知,这完全取决于我。此外,我通常会使用peek()来修改元素的状态,而不是源代码本身,这不会使它有状态或容易产生副作用

forEach的javadoc还说:

The behavior of this operation is explicitly nondeterministic.
当他们对芬丹尼说同样的话时,我理解,但forEach有什么是不确定的呢?如果流未排序,则并行流中的任何操作都不能保证排序。为什么不确定性只针对forEach(和finAny,但它的意思有点不同)

对于peek和forEach,javadoc还包含:

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

再说一遍,为什么只有那里?为什么在剩下的操作中没有提到它呢?

首先,修改对象状态也是一个副作用,因为在执行lambda之后,程序的整体状态会发生变化。如果在并行流中多次使用同一对象,甚至可能会出现并发问题。无副作用函数是一个不改变程序状态的函数,其返回值仅基于其参数。由于要求其他流操作没有副作用,所以没有必要提及它们将在哪个线程和什么时候执行,因为这无关紧要。但若允许操作产生副作用,则应明确提及


即使流是无序的,
forEach
也不同于
forEachOrdered
forEachOrdered
始终保证其lambda不会同时在多个不同的线程中执行。
forEach
调用不仅使流隐式无序,而且还消除了这一保证:您的lambda现在可以并发执行。由于lambda可能会产生副作用,这一点应该明确提及。

好吧,你的问题的两点实际上回答了这个问题。对于普通的中间操作,不确定性是不相关的,因为它们应该没有副作用和不干扰。对于
forEach
,它是“为副作用而设计的”,不确定性很重要,必须记录在案。只有你想要一个正确的答案,这取决于你自己。该规范明确指出,传递给大多数流方法的行为参数是无状态的。这意味着,在存在可能影响计算的副作用的情况下,无法保证您得到正确的答案。因此,通过“为副作用而设计”,它们实际上意味着peek和forEach的实现中有某种东西使它们能够适应副作用,但是其余的函数不能保证相同的?“无副作用函数是一个不改变程序状态的函数,其返回值仅基于其参数”-这不是纯函数的定义吗?无副作用意味着:“局部静态变量、非局部变量、可变引用参数或I/O流不发生突变”。函数可以没有副作用,但返回值仍然不基于其参数。Ex:int f(){return x;}此函数没有副作用,但其返回值随非局部变量而变化。