简体   繁体   English

将嵌套循环转换为流

[英]Convert nested loops into a Stream

I want to replace nested for loops in the following code with streams:我想用流替换以下代码中的嵌套for循环:

private boolean check(St st) {
    List<Co> prereqs = getCoPrereqs();
    
    for (Co prereq : prereqs) {
        
        List<En> stEns = st.getEns();
        boolean flag = false;
        
        for (En en : stEns) {
            if (en.getCo().equals(prereq) && en.getGr() != null) {
                if (en.hasPassedCo()) {
                    flag = true;
                }
            }
            if (!flag)
                return false;
        }
    }
    return true;
}

The two loops and the variable flag is causing confusion.这两个循环和变量标志引起了混乱。 I am not sure if this can be converted to streams totally.我不确定这是否可以完全转换为流。

Probably, you can use nested streams with allMatch .或许,您可以将嵌套流与allMatch一起使用。

I'm saying "probably" because I can't be sure that the code you've proved does what expected, types name are not self-explanatory at all (names in the code matter a lot ) and you have not accompanied the code with any explanations.我说“可能”是因为我不能确定您证明的代码是否符合预期,类型名称根本不是不言自明(代码中的名称很重要)并且您没有附上代码有任何解释。

If I understood your code correctly, you need to validate every Co object returned by getCoPrereqs() and that entails checking each Co object against En object from a List<En> which should be extracted from the method parameter.如果我正确理解了您的代码,您需要验证getCoPrereqs()返回的每个Co对象,这需要根据 List<En> 中的En对象检查每个Co对象,该List<En>应该从方法参数中提取。

That's how it might look like:这就是它的样子:

private boolean check(St st){
    
    return getCoPrereqs().stream()
        .allMatch((Co prereq) -> st.getEns().stream()
            .allMatch((En en) -> en.getCo().equals(prereq)
                            && en.getGr() != null
                            && en.hasPassedCo()
                     ));
}

For readability reasons (to make it more easier to compare stream with loops), I've used explicitly typed lambda expressions (the common practice is to omit types for brevity and let the type inference do the job).出于可读性的原因(为了更容易比较流和循环),我使用了显式类型的 lambda 表达式(为了简洁起见,通常的做法是省略类型,让类型推断来完成工作)。

I have simplified your code somewhat by doing the following:我通过执行以下操作稍微简化了您的代码:

  • removing the boolean flag.删除boolean标志。 It isn't necessary.这是没有必要的。
  • get the List<En> just one time outside of the Prereq loop.在 Prereq 循环之外只获取一次List<En> You can reiterate the original as often as necessary.您可以根据需要经常重复原件。

The major difference is to check for a false return from en.hasPassedCo() and return false immediately.主要区别是检查en.hasPassedCo()false返回并立即返回false Once the iterations are complete, then return true .迭代完成后,返回true

private boolean check(St st) {
        List<Co> prereqs = getCoPrereqs();
        
        List<En> stEns = st.getEns();

        for (Co prereq : prereqs) {           
            for (En en : stEns) {
                if (en.getCo().equals(prereq) && en.getGr() != null) {
                    if (!en.hasPassedCo()) {
                        return false;
                    }
                }
            }
        }
        return true;
}

I'm not certain that streams would improve this (at least not knowing more about the relationships of the fields to each other).我不确定流会改善这一点(至少不知道更多关于字段之间的关系)。 Also, it doesn't make sense how Co relates to en.getCo .此外, Coen.getCo的关系也没有任何意义。 Seems to me that something like prereqs.contains(en.getCo()) would be more appropriate.在我看来,像prereqs.contains(en.getCo())这样的东西会更合适。

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

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