TreeTraversal (final Map<Object, Object> cache) { return intercept("CACHED", new TraversalInterceptor() { @Override public @NotNull <TT> TraversalArgs<TT> intercept(@NotNull TraversalArgs<TT> args) { final Function<? super TT, ? extends Iterable<? extends TT>> tree = args.tree; final class WrappedTree implements Function<TT, Iterable<? extends TT>> { @Override public Iterable<? extends TT> fun(TT t) { //noinspection unchecked return (Iterable<? extends TT>)cache.computeIfAbsent(t, o -> JBIterable.from(tree.fun((TT)o)).collect()); } } if (tree instanceof WrappedTree) { return args; } WrappedTree wrappedTree = new WrappedTree(); return new TraversalArgs<>(args.roots, wrappedTree); } }); }