Search code examples
javafunctional-programmingtail-recursionvavr

Walk a chain of objects recursively in functional style


A common looping pattern in imperative coding styles is to follow a chain of objects to find the end, e.g.:

private ThreadGroup rootOf(ThreadGroup leaf) {
  ThreadGroup rootGroup = leaf;
  ThreadGroup parentGroup;
  while ((parentGroup = rootGroup.getParent()) != null) {
    rootGroup = parentGroup;
  }
  return rootGroup;
}

(from this answer)

I feel like there must be a standard functional pattern that's logically equivalent to this, but I'm not sure what it is. I've come up with the recursive method below using Vavr's Option:

private ThreadGroup rootOf(ThreadGroup leaf) {
  return Option.of(leaf.getParent()) // returns None for null
    .map(this::rootOf)
    .getOrElse(leaf);
}

But it seems as though there ought to be a way to do it without explicit recursion, especially in a language like Java without tail call optimization (I'm imagining something vaguely analogous to foldLeft() but on an iteratively computed value stream, if that makes any sense?)

What's the standard functional approach here?


Solution

  • Stream.iterate + filtering should do it:

    Stream.iterate(leaf, ThreadGroup::getParent)
        .filter(g -> g.getParent() == null)
        .findFirst().get();