Comprehensive Guide to TreeUtil: Building, Traversing, Flattening, and Sorting Tree Structures in Java
This article introduces a versatile Java TreeUtil class that demonstrates how to construct hierarchical tree structures from flat lists, perform pre-order, level-order, and post-order traversals, flatten trees back to lists, and sort nodes using generic functional interfaces, with detailed code examples.
The article begins with an introduction to tree data structures, explaining their hierarchical nature and common use cases such as organization charts, menus, address selectors, and product categories.
It then shows how to define a tree node in Java using a @Data public class MenuVo { private Long id; private Long pId; private String name; private Integer rank = 0; private List subMenus = new ArrayList<>(); } class, where each node holds a list of its children.
Next, the JSON representation of a tree is presented, illustrating how nested objects naturally form a tree.
The core of the article is the TreeUtil utility class. The makeTree method builds a tree from a flat list by filtering root nodes and recursively attaching children using functional interfaces:
public static
List
makeTree(List
list, Predicate
rootCheck, BiFunction
parentCheck, BiConsumer
> setSubChildren) { return list.stream().filter(rootCheck).peek(x -> setSubChildren.accept(x, makeChildren(x, list, parentCheck, setSubChildren))).collect(Collectors.toList()); }Helper methods makeChildren and overloaded versions without generics are also provided to illustrate the step‑by‑step construction of the tree.
Usage examples demonstrate building a menu tree, a department tree, and how to invoke the utility with lambda expressions.
Traversal utilities are included: forPreOrder (pre‑order), forLevelOrder (breadth‑first), and forPostOrder (post‑order). Each method accepts the tree, a Consumer to process each node, and a Function to retrieve child lists.
public static
void forPreOrder(List
tree, Consumer
consumer, Function
> getSubChildren) { for (E l : tree) { consumer.accept(l); List
es = getSubChildren.apply(l); if (es != null && es.size() > 0) { forPreOrder(es, consumer, getSubChildren); } } }A flat method is provided to flatten a tree back into a list while clearing child references:
public static
List
flat(List
tree, Function
> getSubChildren, Consumer
setSubChildren) { List
res = new ArrayList<>(); forPostOrder(tree, item -> { setSubChildren.accept(item); res.add(item); }, getSubChildren); return res; }The article also introduces a sort method that recursively sorts all nodes according to a supplied Comparator :
public static
List
sort(List
tree, Comparator
comparator, Function
> getChildren) { for (E item : tree) { List
childList = getChildren.apply(item); if (childList != null && !childList.isEmpty()) { sort(childList, comparator, getChildren); } } tree.sort(comparator); return tree; }Finally, the article concludes by praising the elegance and reusability of the TreeUtil class, encouraging developers to adopt it for any hierarchical data processing task.
Selected Java Interview Questions
A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!
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.