如何避免嵌套的forEach调用?

时间:2018-12-17 22:05:16

标签: java collections foreach java-8 java-stream

我有以下代码:

interface Device {
    // ...
    boolean isDisconnected();
    void reconnect();
}

interface Gateway {
    // ...
    List<Device> getDevices();
}

...

for (Gateway gateway : gateways) {
    for(Device device : gateway.getDevices()){
        if(device.isDisconnected()){
            device.reconnect();
        }
    }
}

我想使用Stream API重构代码。我的第一次尝试如下:

gateways
    .stream()
    .forEach(
        gateway -> {
            gateway
                .getDevices()
                .parallelStream()
                .filter(device -> device.isDisconnected())
                .forEach(device -> device.reconnect())
            ;
        }
    )
;

我不喜欢它,因此在进行了一些修改之后,我得到了以下代码:

gateways
    .parallelStream()
    .map(gateway -> gateway.getDevices().parallelStream())
    .map(stream -> stream.filter(device -> device.isDisconnected()))
    .forEach(stream -> stream.forEach(device -> device.reconnect()))
;

我的问题是是否有避免嵌套forEach的方法。

3 个答案:

答案 0 :(得分:16)

您应该使用flatMap而不是map来简化流的流:

gateways
    .parallelStream()
    .flatMap(gateway -> gateway.getDevices().parallelStream())
    .filter(device -> device.isDisconnected())
    .forEach(device -> device.reconnect());

我将通过使用方法引用而不是lambda表达式来进一步改进它:

gateways
    .parallelStream()
    .map(Gateway::getDevices)
    .flatMap(List::stream)
    .filter(Device::isDisconnected)
    .forEach(Device::reconnect);

答案 1 :(得分:11)

不要将您的代码重构为使用Streams。这样做对您没有好处,也没有任何好处,因为该代码现在对于将来的维护者来说可读性越来越差,习惯性也越来越少。

通过不使用流,可以避免嵌套forEach语句。

请记住:为了更安全的并行化,流应无副作用。 forEach根据定义引入了副作用。您失去了流的好处,同时失去了可读性,因此根本就不希望这样做。

答案 2 :(得分:4)

在使用并行流之前,我会尝试使用顺序流:

gateways
    .stream()
    .flatMap(gateway -> gateway.getDevices().stream())
    .filter(device -> device.isDisconnected())
    .forEach(device ->  device.reconnect())
;

想法是通过gateways.stream()创建流,然后通过gateway.getDevices()展平flatMap返回的序列。

然后,我们执行一个filter操作,其作用类似于您代码中的if语句,最后,执行一个forEach终端操作,使我们能够在每一个上调用reconnect设备通过了过滤操作。

请参阅Should I always use a parallel stream when possible?