简体   繁体   English

转换为流

[英]Converting to streams

I'd like to convert the following code, which breaks from the outer loop, into Java 8 Stream s. 我想将以下代码从外部循环转换为Java 8 Stream

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;
}

Every answer here uses flatMap , which until java-10 is not lazy . 这里的每个答案都使用flatMap ,直到java-10 不是懒惰的 In your case that would mean that alertActions is traversed entirely, while in the for loop example - not. 在你的情况下,这意味着完全遍历alertActions ,而在for循环示例中 - 不是。 Here is a simplified example: 这是一个简化的例子:

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

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

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

And some usage: 一些用法:

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();
}

In java-8 this will print both one and uno , since flatMap is not lazy. java-8 ,这将同时打印oneuno ,因为flatMap更是不可以偷懒。

On the other hand in java-10 this will print one - and this is what you care about if you want to have your example translated to stream-based 1 to 1. 另一方面,在java-10这将打印one - 如果您希望将示例转换为stream-based 1到1,这就是您所关心的。

Something along the lines of this should suffice: 根据这一点,应该足够了:

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

That said, a better option would be to change the method return type to Optional<CPBTuple> and then simply return the result of findFirst() . 也就是说,更好的选择是将方法返回类型更改为Optional<CPBTuple> ,然后只返回findFirst()的结果。 eg 例如

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();
}

This is better because it better documents the method and helps prevent the issues that arise when dealing with nullity. 这样做更好,因为它更好地记录了该方法,并有助于防止在处理无效时出现的问题。

Since you break out of the loops upon the first match, you can eliminate the loops with a Stream with flatMap, which returns the first available match: 由于你在第一次匹配时突破了循环,你可以使用带有flatMap的Stream来消除循环,它返回第一个可用的匹配:

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);
}

Try this out, 试试这个,

alertsOnCpdDay.stream()
    .map(ConsignmentAlert::getAlertActions)
    .flatMap(List::stream)
    .map(alertAction -> handleAlertAction(reportDTO, consignmentId, alertAction))
    .filter(CPBTuple::isPresent)
    .findFirst().orElse(null);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM