Проходить цепочку объектов рекурсивно в функциональном стиле
Обычный цикл в стилях императивного кодирования состоит в том, чтобы следовать цепочке объектов, чтобы найти конец, например:
private ThreadGroup rootOf(ThreadGroup leaf) {
ThreadGroup rootGroup = leaf;
ThreadGroup parentGroup;
while ((parentGroup = rootGroup.getParent()) != null) {
rootGroup = parentGroup;
}
return rootGroup;
}
(из этого ответа)
Я чувствую, что должен быть стандартный функциональный шаблон, который логически эквивалентен этому, но я не уверен, что это такое. Я придумал рекурсивный метод ниже, используя VavrOption
:
private ThreadGroup rootOf(ThreadGroup leaf) {
return Option.of(leaf.getParent()) // returns None for null
.map(this::rootOf)
.getOrElse(leaf);
}
Но кажется, что должен быть способ сделать это без явной рекурсии, особенно в языке, подобном Java, без оптимизации хвостового вызова (я представляю что-то неопределенно аналогичное foldLeft()
но для итеративно вычисляемого потока создания ценности, если это имеет смысл?)
Какой здесь стандартный функциональный подход?
1 ответ
Решение
Stream.iterate + фильтрация должна сделать это:
Stream.iterate(leaf, ThreadGroup::getParent)
.filter(g -> g.getParent() == null)
.findFirst().get();