I'm trying to build this simple tree:
Multiverse | |--- Universe | |--- Supercluster | |--- Galaxy | |--- Andromeda | |--- Milky way
I came up with this simple method which recursively walk a tree:
/**
* recursively walk a tree structure
*/
public static void recursive(TreeViewItem treeNode){
System.out.println(treeNode.getText());
Iterator<TreeViewItem> itr = treeNode.getItems().iterator();
while (itr.hasNext()) {
TreeViewItem item = (TreeViewItem) itr.next();
recursive(item);
}
}
Is there a better way or more elegant way to do this?
2 Answers 2
You're visiting and printing the tree elements in a depth-first manner, so depthFirstPrint
would be a much better name than "recursive" (which is always a terrible name for any recursive function).
You didn't need this cast:
TreeViewItem item = (TreeViewItem) itr.next();
because you correctly declared the iterator as Iterator<TreeViewItem> itr
As of Java 1.5, you can use a for-each loop, which is simple and elegant:
for (TreeViewItem item : treeNode.getItems()) {
depthFirstPrint(item);
}
There are three kinds of recursive binary tree traversals: pre-order, in-order, and post-order. You've implemented pre-order traversal, so I suggest naming your function preOrderTraversal()
.
Your function is actually doing two things: traversing the tree and printing each node. It would be nice to separate them, so that you have a generic tree traversal algorithm, and a separate place to specify what to do with each node as it is encountered. With Java ≤ 7, this can be done using a visitor pattern. In Java 8, the visitor pattern can be much simpler, since the language allows functions to be passed around easily:
import java.util.function.Consumer;
...
public static void preOrderTraversal(TreeViewItem treeNode, Consumer<TreeViewItem> action) {
action.accept(treeNode);
for (TreeViewItem child : treeNode.getItems()) {
preOrderTraversal(child, action);
}
}
// Call that code with
preOrderTraversal(rootNode, (TreeViewItem node) -> System.out.println(node.getText()));
Your TreeViewItem
class could have a public Iterator<TreeViewItem> iterator()
method, so that TreeViewItem
implements Iterable<TreeViewItem>
to iterate of the children directly, without having to call .getItems()
. Whether you want to make this change depends on whether there might be anything else in a TreeViewItem
that might be worth iterating over, besides the child nodes.