A Reusable Java Utility for Building Tree Structures
This article shares a generic Java utility class that recursively constructs hierarchical tree structures from a flat list by using functional interfaces to identify parent‑child relationships, optionally sorting nodes, and providing a flexible way to set child collections.
In many projects a hierarchical tree representation is required, yet developers often rewrite similar code to assemble the tree from a flat collection of nodes. The author provides a reusable Java utility class, TreeUtils, that encapsulates the whole process.
The core method newTree accepts a list of nodes, the value identifying the root node, a Function to obtain each node's parent value, a Function to obtain the node's own identifier, a BiConsumer to attach a list of child nodes to a parent, and an optional Comparator for sorting. It first checks for an empty input list, then retrieves the top‑level nodes using the helper getChildren. If a comparator is supplied, the top nodes are sorted. The method then recurses: for each top node it determines the node's identifier, calls newTree again to collect its children, and finally invokes the supplied setChildren consumer to attach the child list.
The private helper getChildren filters the original node list by comparing each node's parent value (obtained via parentFunc) with the supplied parentValue. It returns the matching nodes as a list, or null if the input collection is empty.
By abstracting the parent‑lookup, identifier extraction, and child‑attachment logic into functional parameters, the utility works with any object type ( <E>) and any identifier type ( <O>). This makes the class applicable across different domains where tree structures are needed, eliminating the repetitive effort of writing custom tree‑building code each time.
public class TreeUtils {
/**
* Build tree
*
* @param nodes nodes to build tree from
* @param topParentValue root node value
* @param parentFunc function to get parent value
* @param idFunc function to get node id
* @param setChildren consumer to set children list
* @param <E>
* @param <O>
* @return list of top‑level nodes
*/
public static <E, O> List<E> newTree(List<E> nodes, O topParentValue,
Function<E, O> parentFunc, Function<E, O> idFunc,
BiConsumer<E, List<E>> setChildren, Comparator<? super E> c) {
if (CollectionUtils.isEmpty(nodes)) {
return null;
}
List<E> tops = getChildren(nodes, topParentValue, parentFunc);
if (CollectionUtils.isNotEmpty(tops) && c != null) {
Collections.sort(tops, c);
}
if (CollectionUtils.isNotEmpty(tops)) {
for (E node : tops) {
O parentValue = idFunc.apply(node);
List<E> children = newTree(nodes, parentValue, parentFunc, idFunc, setChildren, c);
setChildren.accept(node, children);
}
}
return tops;
}
/**
* Get child nodes
*
* @param nodes
* @param parentValue
* @param parentFunc
* @param <E>
* @param <O>
* @return list of child nodes
*/
private static <E, O> List<E> getChildren(List<E> nodes, O parentValue,
Function<E, O> parentFunc) {
if (CollectionUtils.isEmpty(nodes)) {
return null;
}
return nodes.stream()
.filter(e -> parentFunc.apply(e).equals(parentValue))
.collect(Collectors.toList());
}
}Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
ZhiKe AI
We dissect AI-era technologies, tools, and trends with a hardcore perspective. Focused on large models, agents, MCP, function calling, and hands‑on AI development. No fluff, no hype—only actionable insights, source code, and practical ideas. Get a daily dose of intelligence to simplify tech and make efficiency tangible.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
