public static <T> void depthFirstTraverseTree(
    @NotNull T root,
    @NotNull Function<T, Collection<? extends T>> action
  ) {
    Deque<T> stack = new ArrayDeque<>();
    stack.addFirst(root);
    while (!stack.isEmpty()) {
      T parent = stack.removeFirst();
      List<? extends T> children = new ArrayList<>(action.apply(parent));
      for (int i = children.size() - 1; i >= 0; i--) {
        stack.addFirst(children.get(i));
      }
    }
  }
public static <T> void depthFirstTraverseTree(
    @NotNull T root,
    @NotNull Function<T, Collection<? extends T>> action
  )