2011-03-22 19 views
0

我需要弄清楚如何改進下面的代碼簡化:重構 - 嵌套在Java循環

 for (DirCategory c1 : categories1) { 
      c1.setCount(dirEntryService.getDirEntryCategoryCount(c1)); 
      log.debug("c1: "+c1.getCount()+" - "+c1.getName()); 
      dirCategoryService.persist(c1); 

      List<DirCategory> categories2 = c1.getChildren(); 
      for (DirCategory c2 : categories2) { 
       c2.setCount(dirEntryService.getDirEntryCategoryCount(c2)); 
       log.debug(" c2: "+c2.getCount()+" - "+c2.getName()); 
       dirCategoryService.persist(c2); 

       List<DirCategory> categories3 = c2.getChildren(); 
       for (DirCategory c3 : categories3) { 
        c3.setCount(dirEntryService.getDirEntryCategoryCount(c3)); 
        log.debug(" c3: "+c3.getCount()+" - "+c3.getName()); 
        dirCategoryService.persist(c3); 

        List<DirCategory> categories4 = c3.getChildren(); 
        for (DirCategory c4 : categories4) { 
         c4.setCount(dirEntryService.getDirEntryCategoryCount(c4)); 
         log.debug("  c4: "+c4.getCount()+" - "+c4.getName()); 
         dirCategoryService.persist(c4); 

         List<DirCategory> categories5 = c4.getChildren(); 
         for (DirCategory c5 : categories5) { 
          c5.setCount(dirEntryService.getDirEntryCategoryCount(c5)); 
          log.debug("  c5: "+c5.getCount()+" - "+c5.getName()); 
          dirCategoryService.persist(c5); 

          List<DirCategory> categories6 = c5.getChildren(); 
          for (DirCategory c6 : categories6) { 
           c6.setCount(dirEntryService.getDirEntryCategoryCount(c6)); 
           log.debug("   c6: "+c6.getCount()+" - "+c6.getName()); 
           dirCategoryService.persist(c6); 
          } 
         } 
        } 
       } 
      } 
     } 

我真的很感激這個簡化的「東西」

+1

OMG多麼瘋狂的代碼... – smas 2011-03-22 22:44:11

+0

我的大腦都在牆上。 – 2011-03-22 23:09:25

回答

5

這對於遞歸來說看起來很不錯,因爲所有的循環都有完全相同的結構和內容。遞歸想法是巢所有的循環在一定深度d,用遞歸結構是

  • 嵌套深度爲零是一個空操作,和
  • 嵌套到深度d + 1上做一個for循環深度d的所有環路。

這可以通過調用explore寫成

private static void recursiveExplore(List<DirCategory> categories, int depth) { 
    if (depth == 0) return; 

    for (DirCategory c1 : categories) { 
     c1.setCount(dirEntryService.getDirEntryCategoryCount(c1)); 
     log.debug("c1: "+c1.getCount()+" - "+c1.getName()); 
     dirCategoryService.persist(c1); 

     recursiveExplore(c1.getChildren(), depth - 1); 
    } 
} 
public static void explore(List<DirCategory> categories) { 
    recursiveExplore(categories, 5); 
} 

然後,您可以做探索。

當然,這種方法的工作原理是深度最多爲5。如果你想消除深度要求,只是探索一路下跌到目錄的底部,那麼你可以消除深度參數是這樣的:

public static void explore(List<DirCategory> categories) { 
    for (DirCategory c1 : categories) { 
     c1.setCount(dirEntryService.getDirEntryCategoryCount(c1)); 
     log.debug("c1: "+c1.getCount()+" - "+c1.getName()); 
     dirCategoryService.persist(c1); 

     recursiveExplore(c1.getChildren(), depth - 1); 
    } 
} 

更一般地,嵌套一個你想要的任何時間將任意數量的循環放入另一個循環中,將遞歸視爲一個選項。這是表達這個概念的一個非常普遍的框架。

希望這會有所幫助!

+1

+1限制深度。 – darvids0n 2011-03-22 22:49:24

0

你能不能做到這一點任何幫助遞歸?你應該能夠很好地將這個邏輯嵌套到一個遞歸調用中......你也應該能夠從中獲得一些性能提升。這樣做的另一個好處是它不會影響文件夾嵌套的層次。

Wikipedia article on Recursion

4

神...

void categoryPersister(DirCategory c){ 
    c.setCount(dirEntryService.getDirEntryCategoryCount(c)); 
    log.debug("c: "+c.getCount()+" - "+c.getName()); 
    dirCategoryService.persist(c); 
    for (DirCategory child : c.getChildren()) { 
     categoryPersister(child) ; 
    } 
} 

這樣的事情。

+0

還有一件事。由於我們不知道結構的深度,我認爲最好不要使用調用堆棧。因此我們可以減少StackOverflowError的概率。 – 2011-03-22 22:59:52

+0

@pavelrappo,真的,應該添加某種「級別計數器」,但它是aditional功能;) – 2011-03-23 07:49:31

0

使用遞歸。

void handleChild(List<DirCategory> catgories) { 
    if(categories == null || categories.lenth() == 0) // not sure what the condition is 
     return; 
    else { 
     for(DirCategory cat : catgories) { 
     // do stuff 
      handleChild(cat.getChild()) 
     } 

    } 

} 
0

你必須愛遞歸:

public void persist(DirCategory category, int level) { 
    category.setCount(dirEntryService.getDirEntryCategoryCount(category)); 
    log.debug(level + ": "+category.getCount()+" - "+category.getName()); 
    dirCategoryService.persist(category); 
    List<DirCategory> catChildren = cateogyr.getChildren(); 
    for (DirCategory child : catChildren) { 
     persist(child, level + 1); 
    } 
}  

內部代碼:

persist(c1); 
0

寫了兩個方法:

1檢索DirCategory,第二個用於檢索的孩子。像這樣的:

private void retrieveDirCategory(DirCategory c) { 
    c.setCount(dirEntryService.getDirEntryCategoryCount(c)); 
    log.debug("c: "+c.getCount()+" - "+c.getName()); 
    dirCategoryService.persist(c);  
} 

private void retrieveDeep(Collections<DirCategory> categories, int deep) { 
    if (deep == 0) { 
     return; 
    } 

    for (DirCategory c : categories) { 
     retrieveDirCategory(c); 
     retrieveDeep(c.getChildren(), deep-1); 
    } 
} 
// and you call: 
// retrieveDeep(categories1, 6);