Простой вопрос задается в основном из любопытства о том, что Java Compilers достаточно умны, чтобы сделать. Я знаю, что не все компиляторы построены одинаково, но мне интересно, считается ли другие разумно ожидать оптимизации на большинство компиляторов, с которыми я, вероятно, сталкиваюсь, а не, если она работает на определенной версии или на всех версиях.
Итак, скажем, у меня есть какая -то структура дерева, и я хочу собрать всего потока узла. Есть два простых способа сделать это рекурсивно.
public Set getDescendants(){
Set descendants=new HashSet();
descendants.addall(getChildren());
for(Node child: getChildren()){
descendants.addall(child.getDescendants());
}
return descendants;
}
< /code>
Тем не менее, при условии, что нет оптимизации компилятора и дерева приличного размера, это может стать довольно дорого. При каждом рекурсивном вызове я создаю и полностью заполняю набор, только для того, чтобы вернуть этот стек, чтобы метод вызова мог добавить содержимое моего возвращающегося набора в это версия набора потомков, отбрасывая версию Это было просто построено и населено в рекурсивном вызове. < /p>
Так что теперь я создаю множество наборов, просто чтобы их отказались, как только я возвращаю их содержимое. Я не только оплачиваю незначительную стоимость инициализации за строительство наборов, но и плачу более существенную стоимость перемещения всего содержимого одного набора в более крупный набор. На больших деревьях большая часть моего времени тратится на перемещающиеся узлы в памяти от сета А к Б. Я думаю, что это даже делает мой алгоритм O (n^2) вместо O (n) из -за времени, проведенного копированием узлов; Хотя это может решить, чтобы быть O (n log (n)), если я настроен на математику. вспомогательный метод, который выглядит так: < /p>
public Set getDescendants(){
Set descendants=new HashSet();
getDescendantsHelper(descendants);
return descendants;
}
public Set getDescendantsHelper(Set descendants){
descendants.addall(getChildren());
for(Node child: getChildren()){
child.getDescendantsHelper(descendant);
}
return nodes;
}
< /code>
Это гарантирует, что я когда -либо создаю один набор, и мне не нужно тратить время на копирование от одного набора в другой. Тем не менее, это требует написания двух методов вместо одного и, как правило, кажется немного более громоздким. < /P>
Вопрос в Оптимизация такого рода метода? Или я могу разумно ожидать, что компилятор Java или JIT признать, что я создаю только временные наборы для удобства возвращения к вызову и избежать расточительного копирования между наборами? < /p>
< P> РЕДАКТИРОВАТЬ: Уборка плохой копии вставки, которая приводит к моему образцу метода, добавляя все дважды. Вы знаете, что что -то плохое, когда ваш «оптимизированный» код медленнее, чем ваш обычный код.
Подробнее здесь: https://stackoverflow.com/questions/231 ... ve-methods