使用 Stream 映射单个对象

let*_*ive 4 java design-patterns

这是java 8 Stream的一个很好的用例吗:

final Car carWithInterior = Stream.of(carWithEngine)
            .map(car -> installSeats.execute(car))
            .map(car -> installDashBoard.execute(car))
            .map(car -> installSunRoof.execute(car))
            .collect(car);
Run Code Online (Sandbox Code Playgroud)

carWithEngine是一个Car。请注意,有时即使汽车(带仪表板)被传递到 installSunroof,它也不会执行任何操作,因为屋顶上没有孔。我应该总是在安装/映射过程结束得到一辆车

安装顺序是必需的(这就是为什么我认为它流)和一个安装有时可能需要从通汽车实例的参数来执行它的操作。

  1. 这是 java 8 的 Stream 的一个很好的用例吗?

  2. 很明显,我最后的收藏是不对的。我应该如何在这条安装/装配线的末端拿到汽车?findFirst().get()会起作用,但我认为这很糟糕,因为即使安装没有对 做任何事情carWitEngine并且我没有流式传输多个元素,我也应该总是在最后得到一辆车。

我不确定汽车是如何组装的,但假设为了这个类比,您需要先安装发动机,然后再添加内饰

Dan*_*ejo 6

回答您的问题:

  1. 这是 java 8 Stream 的一个很好的用例吗?

不,Java Stream Api 旨在用于集合。从这里开始,流的定义是:

来自支持聚合操作的源的元素序列

您有一个不是元素序列的单个对象,因此使用 Stream 会使您的代码更难以理解。要回答问题2,你可以这样做

findFirst().orElse(carWithEngine)
Run Code Online (Sandbox Code Playgroud)

您的示例的替代方法是简单地嵌套函数调用,如下所示:

installSunRoof.execute(installDashBoard.execute(installSeats.execute(car)))
Run Code Online (Sandbox Code Playgroud)

另一种选择是在汽车上定义一个安装方法,该方法接收 BaseIinstaller 并返回修改后的汽车,如下所示:

final Car carWithInterior = car.install(installSeats)
                               .install(installDashBoard)
                               .install(installSunRoof);
Run Code Online (Sandbox Code Playgroud)


shi*_*njw 5

由于您希望对单个对象执行操作。Java 8 Optional是合适的。

生成器模式(菲尔C'S评论)绝对是值得一游,如果这些地图操作简单水合Car对象。

  1. 为单个对象打开一个流对于流来说不是一个好的用例。
  2. 如果Car通过.map()操作将其丢弃在流中,则您正在冒险进入危险领域(副作用)。在处理时Streams,强烈建议按预期方式使用这些操作。如果您打算从流中删除元素.filter()

编辑 OP 的编辑:

关于“序列”及其如何翻译存在一些基本的混淆

可选的

 car => map(execute) => map(execute) => transformedcar
Run Code Online (Sandbox Code Playgroud)

[car1, car2, car3]
     => map(execute) => map(execute) => updatedcar1                |  => findFirst (Optional<Car>)
           => map(execute) => map(execute) =>  updatedcar2         |
                 => map(execute) => map(execute) => updatedcar3    |
                                                                collect
                                                 [updatedcar1, updatedcar2, updatedcar3]
Run Code Online (Sandbox Code Playgroud)

findFirst方法将返回一个Optional. 该collect方法将提供一个终端操作,让您聚合/减少/分组这些结果。

这些map操作“按顺序”转换传递的元素。但是Stream,在您必须处理许多或“一系列”汽车的情况下,这将是合适的情况。

重温 #2

您可以选择使用 Optional 提供替代方案orElse(car)

但这就是您必须对正在执行的副作用产生争议的地方。

如果 execute 方法正在操作并返回传递给它的同一个对象,则会出现意想不到的后果。例如,我将使用 Optionals,但同样适用于 Streams。

private final Car car Optional.of(carWithEngine)
   .map(installSunroof.execute)   // <-- updatedCarWithSunroof
   .map(installDashboard.execute) // <-- updatedCarWithSunroofAndDashboard
   .orElse(carWithEngine)         // <-- updatedCarWithSunroofAndDashboard
Run Code Online (Sandbox Code Playgroud)