替代多个嵌套for和if块

Swa*_*nil -1 java foreach nested-loops java-8 java-stream

我正在尝试实现一个复杂的块,我使用多个for循环编写,如果条件更复杂的东西.最初的代码是

for(Coll_Monthly_Main monthlyAccount:monthlyList){
        for(Coll_Daily_Main dailyAccount:dailyList){
            if(monthlyAccount.getAccountId().trim().equals(dailyAccount.getAccountId().trim())){
                for(Catg_Monthly monthlyCategory: monthlyAccount.getCatg()){
                    for(Catg_Daily dailyCategory: dailyAccount.getCatg()){
                        if(monthlyCategory.getPriCatId().trim().equals(dailyCategory.getPriCatId().trim())){
                            monthlyCategory.setMthTtl(dailyCategory.getMthTtl());
                            monthlyCategory.setMtd(dailyCategory.getMtd());
                            monthlyCategory.setYtd(dailyCategory.getYtd());

                            for(SecCatDtl_Mthly monthlySecCategory:monthlyCategory.getSecCatDtl()){
                                for(SecCatDtl_Daily dailySecCategory:dailyCategory.getSecCatDtl()){
                                    if(monthlySecCategory.getCatId().trim().equals(dailySecCategory.getCatId().trim())){
                                        monthlySecCategory.setMthTtl(dailySecCategory.getMthTtl());
                                        monthlySecCategory.setMtd(dailySecCategory.getMtd());
                                        monthlySecCategory.setYtd(dailySecCategory.getYtd());
                                    }
                                }
                            }
                        }

                    }
                }
            }
        }
    }
    return monthlyList;
Run Code Online (Sandbox Code Playgroud)

我已经按照这个答案设法实现了第一级如下: -

monthlyList.forEach(coll_mthly->{
        dailyList.stream().filter(coll_daily->coll_mthly.getAccountId().trim().equals(coll_daily.getAccountId().trim()))
        .forEach(catg_mth->coll_mthly.getCatg())->{

        };
    });
Run Code Online (Sandbox Code Playgroud)

对于下一级嵌套,我需要循环嵌套列表,我不知道如何继续它.我不断收到如下语法错误: - 令牌上的语法错误,而不是TypeElidedFormalParameter

我很欣赏正确方向的任何指示.

更新: - 按照托马斯的回答,这就是它的样子

Map<String, Coll_Daily_Main> dailies = dailyList.stream().collect(Collectors.toMap(cdm -> cdm.getAccountId(), cdm-> cdm) );

    for(Coll_Monthly_Main monthlyAccount : monthlyList) {
        Coll_Daily_Main dailiesForAccount  = dailies.get( monthlyAccount.getAccountId().trim());

          Map<String, Catg_Daily> dailyCatgories=dailiesForAccount.getCatg().stream().collect(Collectors.toMap(cv->cv.getPriCatId(), cv->cv));
          for(Catg_Monthly monthlyCategory:monthlyAccount.getCatg()){
              Catg_Daily dailyCategory = dailyCatgories.get(monthlyCategory.getPriCatId().trim());
              if(dailyCategory!=null){
                monthlyCategory.setMthTtl(dailyCategory.getMthTtl());
                monthlyCategory.setMtd(dailyCategory.getMtd());
                monthlyCategory.setYtd(dailyCategory.getYtd());

                Map<String,SecCatDtl_Daily> dailySecCategories=dailyCategory.getSecCatDtl().stream().collect(Collectors.toMap(fg->fg.getCatId(), fg->fg));
                for(SecCatDtl_Mthly monthlySecCategory:monthlyCategory.getSecCatDtl()){
                    SecCatDtl_Daily dailySecCategory =dailySecCategories.get(monthlySecCategory.getCatId().trim());
                    if(dailySecCategory!=null){
                    monthlySecCategory.setMthTtl(dailySecCategory.getMthTtl());
                    monthlySecCategory.setMtd(dailySecCategory.getMtd());
                    monthlySecCategory.setYtd(dailySecCategory.getYtd());
                    }
                }
              }
          }
        }
Run Code Online (Sandbox Code Playgroud)

Tho*_*mas 5

正如其他人已经多次说过的那样,最好重新考虑一下你的方法,使其更具可读性,但也更快.有一件事我想到:你有3个级别,包括2个循环和一个if来检查元素是否匹配(通过id).这些级别将具有O(n*m)复杂度.

但是,您可以尝试使用id作为键来构建映射或多图(Guava有一些)并将其降低到O(n + m):

  • O(n)用于构建地图(理想情况下在较大的集合上,即每天)
  • O(m)用于迭代第二组(理想情况下是较小的集合,即每月)
  • 查找应为O(1),因此可以忽略

我不确定所有这些嵌套级别是什么意思所以我只能给出一个你可以为一个级别做什么的例子(我将采取第一个):

//I'm using Google Guava's classes here
SetMultimap<String, Coll_Daily_Main> dailies = ...;//use one that fits your needs

//Iterate over n daily entries and put them into the map which should be O(n)
dailyList.forEach( cdm -> dailies.put( cdm.getAccountId().trim(), cdm ) );

//Iterate over the (smaller) set of monthly entries and do a lookup for the dailies which should be O(m)
for(Coll_Monthly_Main monthlyAccount : monthlyList) {
  Set<Coll_Daily_Main> dailiesForAccount = dailies.get( monthlyAccount.getAccountId().trim() );

  //level done, either go down to the next or try to further straighten it out or optimize
}
Run Code Online (Sandbox Code Playgroud)

更新:

我忘了提到你不必在Java 8中使用Guava.虽然定义看起来有点尴尬,使用a Map<String, Set<Coll_Daily_Main>>不再那么"难"了:

 Map<String, Set<String>> dailies = new HashMap<>();
 dailyList.forEach( cdm -> dailies.computeIfAbsent( cdm.getAccountId().trim(), v -> new HashSet<>() ).add( cdm  ) );
Run Code Online (Sandbox Code Playgroud)

注意:您也可以使用收集器使其缩短一行.这是否更容易阅读和使用是辩论.

Map<String, Set<Daily>> dailies = 
    dailyList.stream().collect( Collectors.groupingBy( cdm -> cdm.getAccountId().trim(), 
                                                       Collectors.toSet() ) );
Run Code Online (Sandbox Code Playgroud)