Проходить цепочку объектов рекурсивно в функциональном стиле

Обычный цикл в стилях императивного кодирования состоит в том, чтобы следовать цепочке объектов, чтобы найти конец, например:

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();
Другие вопросы по тегам