Рефакторинг - Упрощение вложенных циклов в Java - PullRequest
1 голос
/ 23 марта 2011

Мне нужно выяснить, как улучшить следующий код:

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

Я был бы очень признателен за любую помощь в упрощении этой "вещи"

Ответы [ 6 ]

8 голосов
/ 23 марта 2011

Это похоже на отличную работу для рекурсии, поскольку все циклы имеют одинаковую структуру и содержание.Рекурсивная идея состоит в том, чтобы вложить все циклы на некоторую глубину d, при этом рекурсивная структура имеет вид

  • Вложение в нулевую глубину не допускается, а
  • Вложение в глубину d +1 выполняет цикл for для всех циклов глубины d.

Это можно записать как

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

Затем вы можете выполнить исследование, позвонив по номеру explore.

Конечно, этот подход работает с предположением, что глубина составляет не более пяти.Если вы хотите исключить требование глубины и просто изучить весь путь до самого конца каталога, то вы можете просто исключить параметр глубины, например, такой:

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

В более широком смысле, в любое время, когда вы захотитевложите произвольное число циклов друг в друга, рассмотрите рекурсию как вариант.Это очень общая структура для выражения этой концепции.

Надеюсь, это поможет!

4 голосов
/ 23 марта 2011
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 голосов
/ 23 марта 2011

Напишите два метода:

1-й для получения DirCategory, 2-й для получения дочерних.Как то так:

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 голосов
/ 23 марта 2011

Вы должны любить рекурсию:

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 голосов
/ 23 марта 2011

Использовать рекурсию.

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 голосов
/ 23 марта 2011

Разве вы не можете сделать это рекурсивно?Вы должны уметь втиснуть эту логику в рекурсивный вызов довольно красиво ... Вы также сможете получить от этого прирост производительности.Еще одним преимуществом такого подхода является то, что не имеет значения, сколько уровней вложены в ваши папки.

Статья в Википедии о рекурсии

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...