开发者

Refactoring - Simplifying nested for loops in java

I need to figure out how to improve following code:

      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(di开发者_如何学PythonrEntryService.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);
                            }
                        }
                    }
                }
            }
        }

I would really appreciate any help simplifying this "thing"


This looks like a great job for recursion, since all of the loops have exactly the same structure and content. The recursive idea is to nest all the loops to some depth d, with the recursive structure being

  • Nesting to depth zero is a no-op, and
  • Nesting to depth d + 1 does a for loop over all loops of depth d.

This could be written as

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

You can then do the exploration by calling explore.

Of course, this approach works with the assumption that the depth is at most five. If you want to eliminate the depth requirement and just explore all the way down to the bottom of the directory, then you can just eliminate the depth parameter like this:

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

More generally, any time you want to nest an arbitrary number of loops inside of one another, consider recursion as an option. It's a very general framework for expressing this concept.

Hope this helps!


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

something like this.


Can't you do this recursively? You should be able to nest this logic into a recursive call pretty nicely... You should be able to get some performance gains out of this as well. Another advantage to doing it this way is that it won't matter how many levels your folders are nested.

Wikipedia article on Recursion


Use recursion.

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

     }

}


You gotta love recursion:

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

Inside your code:

persist(c1);


Write two methods:

1st for retrieving DirCategory, 2nd for retrieving children. Something like this:

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜