Java 8将函数应用于Stream的所有元素,而不会破坏流链

ale*_*lov 30 java chaining java-8 java-stream

在Java中是否有办法将函数应用于a的所有元素Stream而不破坏Stream链?我知道我可以打电话forEach,但那个方法会返回一个void,而不是一个Stream.

Boh*_*ian 32

有(至少)3种方式.为了示例代码,我假设您要调用2个使用者方法,methodA并且methodB:

A.使用peek():

list.stream().peek(x -> methodA(x)).forEach(x -> methodB(x));
Run Code Online (Sandbox Code Playgroud)

虽然文档说只使用它进行"调试",但它有效(现在正在生产中)

B. map()用于调用methodA,然后将元素返回到流:

list.stream().map(x -> {method1(x); return x;}).forEach(x -> methodB(x));
Run Code Online (Sandbox Code Playgroud)

这可能是最"可接受"的方法.

C.做两件事forEach():

list.stream().forEach(x -> {method1(x); methodB(x);});
Run Code Online (Sandbox Code Playgroud)

这是最不灵活的,可能不适合您的需要.

  • 您对“副作用”的定义与其他IT世界的定义不符。这特别危险,因为像Stream API这样的API文档(不鼓励函数中的副作用)引用标准定义,例如[Wikipedia](https://en.wikipedia.org/wiki/Side_effect_(computer_science)) :“ *在计算机科学中,如果函数或表达式在其范围之外修改了某些状态或与其调用函数或外界有可观察的交互作用,则称其为副作用”。这是有意还是无意的都无关紧要。 (4认同)
  • @holger 不正确。Method1 可能会用它做一些事情,而不会发生突变。当我想在流的中途收集元素(到 Set,不是时间关键的,即没问题)时,我实际上使用了这个确切的模式(`peek()` 版本),但也将流的尾部发送到消费者通过 forEach()。不是没用。 (3认同)
  • 在`map`函数中执行带副作用的动作以及使用`peek`进行这种(非调试)副作用的含义基本相同. (2认同)
  • 如果没有副作用,则调用method1(x);完全是没有用的。 (2认同)
  • @holger “副作用”是*未公布*和/或*意外*的状态变化。显然,通过添加 Set 会发生变异,但这是意料之中的,所以它不是“副作用”。如果消费者在没有宣传的情况下对元素进行了变异,那将是一个副作用。您似乎不是在说,如果在调用方法时“某些事情发生了变化”,那么它就会产生副作用,但这是无稽之谈。如果一个方法*应该*改变某些东西,那么它就不是副作用;这是预期的行为。 (2认同)
  • 选项 C,`forEach`,不返回流,因此您无法继续处理流。 (2认同)

cse*_*nga 5

您正在寻找Streammap()功能。

例:

List<String> strings = stream
.map(Object::toString)
.collect(ArrayList::new, ArrayList::add, ArrayList::addAll);
Run Code Online (Sandbox Code Playgroud)

  • 地图不是在流元素上采取操作的正确位置,它是将项目“转换”为其他内容的正确位置。 (3认同)