copyrist.add(s); list.stream().forEach(使用者);,java,java-8,functional-programming,Java,Java 8,Functional Programming" /> copyrist.add(s); list.stream().forEach(使用者);,java,java-8,functional-programming,Java,Java 8,Functional Programming" />

java 8中lambda表达式的副作用 请考虑下面的代码片段。 List<String> list = new ArrayList<String>(); list.add("A"); list.add("B"); list.add("C"); List<String> copyList = new ArrayList<String>(); Consumer<String> consumer = s->copyList.add(s); list.stream().forEach(consumer); List List=new ArrayList(); 列表。添加(“A”); 列表。添加(“B”); 列表。添加(“C”); List copyList=new ArrayList(); 消费者消费者=s->copyrist.add(s); list.stream().forEach(使用者);

java 8中lambda表达式的副作用 请考虑下面的代码片段。 List<String> list = new ArrayList<String>(); list.add("A"); list.add("B"); list.add("C"); List<String> copyList = new ArrayList<String>(); Consumer<String> consumer = s->copyList.add(s); list.stream().forEach(consumer); List List=new ArrayList(); 列表。添加(“A”); 列表。添加(“B”); 列表。添加(“C”); List copyList=new ArrayList(); 消费者消费者=s->copyrist.add(s); list.stream().forEach(使用者);,java,java-8,functional-programming,Java,Java 8,Functional Programming,由于我们使用lambda表达式,根据函数编程(纯函数),它应该只计算输入并提供相应的输出 但在本例中,它试图向列表中添加既不是输入也不是在lambda范围内声明的元素 我的意思是,这是一种好的做法,会导致任何副作用吗?forEach如果不产生副作用,将是无用的,因为它没有返回值。因此,无论何时使用forEach,您都应该预期会发生副作用。因此,你的例子没有错 消费者可以打印字符串,或将其插入某个数据库,或将其写入某个输出文件,或将其存储在某个集合(如您的示例所示)中,等等 从流Javadoc:

由于我们使用lambda表达式,根据函数编程(纯函数),它应该只计算输入并提供相应的输出

但在本例中,它试图向列表中添加既不是输入也不是在lambda范围内声明的元素


我的意思是,这是一种好的做法,会导致任何副作用吗?

forEach
如果不产生副作用,将是无用的,因为它没有返回值。因此,无论何时使用
forEach
,您都应该预期会发生副作用。因此,你的例子没有错

消费者
可以打印
字符串
,或将其插入某个数据库,或将其写入某个输出文件,或将其存储在某个
集合
(如您的示例所示)中,等等

Javadoc:

流管道由源(可能是数组、集合、生成器函数、I/O通道等)、零个或多个中间操作(将流转换为另一个流,例如stream.filter(谓词))和终端操作组成(产生结果或副作用,如Stream.count()或Stream.forEach(Consumer))

此外,如果您查看
Consumer
的Javadoc,您会发现它预期会有副作用:

java.util.function.Consumer

表示接受单个输入参数且不返回结果的操作。与大多数其他功能接口不同,使用者应通过副作用进行操作


我想这意味着Java
Stream
s和函数接口并不是专门为“纯”函数式编程而设计的。

对于
forEach
甚至是
Stream()。forEach
非常简单。您的示例很好。

List<String> lst = Arrays.asList("a", "b", "c");

lst.stream().map(
 s -> {
   System.out.println(s);
   return "-";
 });
List<String> list = Arrays.asList("A", "B", "C");

// this is the base pattern for transforming one list to another.
// the map applies a transformation.
List<String> copyList1 = list.stream().map(e -> e).collect(Collectors.toList());

// if it's a 1-to-1 mapping, then you don't really need the map.
List<String> copyList2 = list.stream().collect(Collectors.toList());

// in essence, you could of course just clone the list without streaming.
List<String> copyList3 = new ArrayList<>(list);
请注意,如果您使用其他流媒体方法执行此操作,那么您可能会得到一些惊喜:例如,以下代码完全不打印任何内容。

List<String> lst = Arrays.asList("a", "b", "c");

lst.stream().map(
 s -> {
   System.out.println(s);
   return "-";
 });
List<String> list = Arrays.asList("A", "B", "C");

// this is the base pattern for transforming one list to another.
// the map applies a transformation.
List<String> copyList1 = list.stream().map(e -> e).collect(Collectors.toList());

// if it's a 1-to-1 mapping, then you don't really need the map.
List<String> copyList2 = list.stream().collect(Collectors.toList());

// in essence, you could of course just clone the list without streaming.
List<String> copyList3 = new ArrayList<>(list);

最后一行可以重构为
list.stream().forEach(copyList::add)
forEach
从来都不是纯粹的功能性的,因为没有副作用,它不会对流做任何事情。对于Scheme,
数组中的每个
,这是正确的。forEach在JS中,…更一般地说,消费者是为了产生副作用。