flatMap后引用原始对象

问题描述 投票:0回答:3

flatMap后是否可以引用原始对象?

例如:

.flatMap(passenger-> passenger.getAncillaries().stream())                                                                    
.forEach(ancillary -> {
    [Can here reference passenger?]
    foo(passenger, ancillary); ?????
}

谢谢。

问候。

java java-stream flatmap
3个回答
1
投票

在 Java 17 中,您可以使用

record
来做到这一点(旧版本中的类也可以):

record PassengerAndAncillary(Passenger passenger, Ancillary ancillary) {}

// 
passengers.flatMap(passenger-> passenger.getAncillaries()
                              .stream()
                              .map(ancillary -> new PassengerAndAncillary(passenger, ancillary)                                                                    )
.forEach(pa -> {
    foo(pa.passenger(), pa.ancillary());
});

然后更好:让 foo 接受 PassengerAndAncillary,你就完成了:

.forEach(this::foo)

如果不想自己上课,也可以用:

然而,在这种情况下,如果您不使用

Stream
,最好不要使用
Stream

passengers.forEach(passenger -> {
  passenger.getAncillaries().forEach(ancillary -> {
    foo(passenger, ancillary);
  });
});

-- 编辑(评论):

我会说之前/之后的过滤归结为性能问题:

  • 如果你不使用过滤器也不使用并行流,我认为基于
    forEach
    的循环会更好,因为你根本没有使用
    Stream
    .
  • 如果您只需要对乘客进行过滤,请在
    flatMap
    之前进行:生成的流将更短,从而减少对
    flatMap
    函数的调用(以及更少的
    record PassengerAndAncillary
    )。
  • 如果您只需要过滤辅助(而不是两者),请在 flatMap 函数中执行此操作:您不会为不匹配的辅助创建不必要的对象。
  • 如果您需要同时执行这两项操作,请在
    forEach
    之前执行
    PassengerAndAncillary

0
投票

在代码行中:

.flatMap(passenger-> passenger.getAncillaries().stream())  
// Only Ancillaries type objects exist in the stream

所以你不能写这样的代码:

.forEach(ancillary -> {
    passenger.getName();// can not access to the passenger object
}

正确答案:

.flatMap(passenger-> passenger.getAncillaries().stream())                                                                    
.forEach(item -> {
    item.getXXX();//item references 【passenger.getAncillaries()】
}

0
投票

使用

flatMap
的另一个替代方法是将 mapMulti(Java 16)Map.entry

结合使用
  • 像往常一样串流乘客
  • 你可以根据需要过滤乘客。如果过滤谓词返回 true,过滤后的对象将通过。
  • 然后调用
    mapMulti
    ,它获取流对象和消费者。请注意,mapMulti 是类型见证的,以反映放置在流上的新类型。在这种情况下
    Map.Entry
  • 使用循环遍历辅助列表,然后在
    Map.Entry
    中打包。
    Consumer.accept
    将其放在流中以进行后续处理。
passengers.stream()
       .filter(passenger -> passenger.isSomething)
              .<Map.Entry<Passenger, Ancillary>>mapMulti((passenger, consumer) -> {
                    for (Ancillary ancillary : passenger.getAncillaries) {
                        consumer.accept(
                                Map.entry(passenger, ancillary));
                    }
                })
        .forEach(e -> foo(e.getKey(), e.getValue()));
© www.soinside.com 2019 - 2024. All rights reserved.