Преобразование в потоки - PullRequest
0 голосов
/ 07 июня 2018

Я хотел бы преобразовать следующий код, который выходит из внешнего цикла, в Java 8 Stream s.

private CPBTuple getTuple(Collection<ConsignmentAlert>  alertsOnCpdDay)
{
    CPBTuple cpbTuple=null;

    OUTER:
    for (ConsignmentAlert consignmentAlert : alertsOnCpdDay) {
        List<AlertAction> alertActions = consignmentAlert.getAlertActions();
        for (AlertAction alertAction : alertActions) {
            cpbTuple = handleAlertAction(reportDTO, consignmentId, alertAction);
            if (cpbTuple.isPresent()) {
                break OUTER;
            }
        }
    }
    return cpbTuple;
}

Ответы [ 4 ]

0 голосов
/ 07 июня 2018

Каждый ответ здесь использует flatMap, который до java-10 не ленится .В вашем случае это будет означать, что alertActions пройден полностью, а в примере цикла for - нет.Вот упрощенный пример:

static class User {
    private final List<String> nickNames;

    public User(List<String> nickNames) {
        this.nickNames = nickNames;
    }

    public List<String> getNickNames() {
        return nickNames;
    }
}

И некоторое использование:

public static void main(String[] args) {
    Arrays.asList(new User(Arrays.asList("one", "uno")))
            .stream()
            .flatMap(x -> x.getNickNames().stream())
            .peek(System.out::println)
            .filter(x -> x.equalsIgnoreCase("one"))
            .findFirst()
            .get();
}

В java-8 это напечатает и one и uno,так как flatMap не ленив.

С другой стороны, в java-10 это напечатает one - и это то, что вас волнует, если вы хотите, чтобы ваш пример был переведен в stream-based 1 в1.

0 голосов
/ 07 июня 2018

Что-то вроде этого должно быть достаточно:

return alertsOnCpdDay.stream()
              .flatMap(s-> s.getAlertActions().stream())
              .map(s-> handleAlertAction(reportDTO, consignmentId, s))
              .filter(s-> s.isPresent())
              .findFirst().orElse(null);

Тем не менее, лучшим вариантом будет изменить тип возвращаемого значения метода на Optional<CPBTuple>, а затем просто вернуть результат findFirst().например,

private Optional<CPBTuple> getTuple(Collection<ConsignmentAlert> alertsOnCpdDay) {
    return alertsOnCpdDay.stream()
                  .flatMap(s-> s.getAlertActions().stream())
                  .map(s-> handleAlertAction(reportDTO, consignmentId, s))
                  .filter(s-> s.isPresent())
                  .findFirst();
}

Это лучше, потому что оно лучше документирует метод и помогает предотвратить проблемы, возникающие при работе с недействительностью.

0 голосов
/ 07 июня 2018

Попробуйте,

alertsOnCpdDay.stream()
    .map(ConsignmentAlert::getAlertActions)
    .flatMap(List::stream)
    .map(alertAction -> handleAlertAction(reportDTO, consignmentId, alertAction))
    .filter(CPBTuple::isPresent)
    .findFirst().orElse(null);
0 голосов
/ 07 июня 2018

Поскольку вы разрываете циклы при первом совпадении, вы можете устранить циклы с помощью Stream с flatMap, который возвращает первое доступное совпадение:

private CPBTuple getTuple(Collection<ConsignmentAlert> alertsOnCpdDay) {
    return alertsOnCpdDay.stream()
                         .flatMap(ca -> ca.getAlertActions().stream())
                         .map(aa -> handleAlertAction(reportDTO, consignmentId, aa))
                         .filter(CPBTuple::isPresent)
                         .findFirst()
                         .orElse(null);
}
...