替代多个嵌套for和if块

时间:2018-01-26 11:06:37

标签: java foreach java-8 java-stream nested-loops

我正在尝试实现一个复杂的块,我用多个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;

我已经按照answer进行了操作,并设法实现了以下第一级: -

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

        };
    });

对于下一级嵌套,我需要遍历嵌套列表,我不知道如何继续它。我不断收到如下语法错误: -  令牌上的语法错误,而不是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());
                    }
                }
              }
          }
        }

2 个答案:

答案 0 :(得分: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
}

<强>更新

我忘了提到你不必在Java 8中使用Guava。虽然使用Map<String, Set<Coll_Daily_Main>>定义看起来有点尴尬但是&#34;硬&#34 ;了:

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

注意:您也可以使用收藏家使其缩短一行。这是否易于阅读和使用是有争议的。

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

答案 1 :(得分:2)

  • 首先,您需要以私有方法提取所有if语句。
  • 然后你可以开始用lambdas重构你的for语句。

您甚至可以声明一个静态函数(在下面的示例中称为john.pdf)来导出嵌套循环逻辑:

loop