One hole in the Java collection classes is no tree. I have seen in production code in a prior job in non-UI software developers choose to use Swing JTree as a replacement collection for a tree data structure.
Rather than take that tortured path, here is a straight-forward tree interface:
/** * {@code TreeList} is a list with left-to-right, depth-first traversal over a * tree. There is no limitation to the number of child nodes for a given node. * <p/> * Ordinary {@code List} operations behave as if they were operation on a list * of node values. For example, given a any tree list node, say * <var>node</var>, then {@code node.getValue()} and {@code node.get(0)} are the * same object. * * @author <a href="mailto:binkley@alumni.rice.edu">B. K. Oxley (binkley)</a> */ public interface TreeList<E> extends List<E> { /** * Checks if this node is a root node, this is, has no parent. * * @return {@code true} if a root node */ boolean isRoot(); /** * Gets the parent of this node or throw {@code NoSuchElementException} if * this is a root node, hence, never {@code null}. * * @return the node parent, if any * * @throws NoSuchElementException if this is a root node * @see #isRoot() */ TreeList<E> getParent(); /** * Checks if this node is a leaf node, that is, has no children. * * @return {@code true} if a leaf node */ boolean isLeaf(); /** * Gets the list of child nodes or an empty list if none, hence, never * {@code null}. * <p/> * The list is read-write. Changes to the list are reflected in the tree. * * @return the child nodes, if any, or the empty list */ List<TreeList<E>> children(); /** * Adds a child node to this node with the given <var>value</var> to the end * of the list of children. The new node has this node as its parent. * * @param value the new child node value * * @return the child node */ TreeList<E> addChild(final E value); /** * Adds a child node to this node with the given <var>value</var> to the * <var>index</var> position in the list of children. The new node has this * node as its parent. * * @param index the new child position, 0-based * @param value the new child node value * * @return the child node * * @throws IndexOutOfBoundsException if <var>index</var> is negative or * larger than the count of children of this node */ TreeList<E> addChild(final int index, final E value); /** * Removes the given <var>child</var> node from this node. * * @param child the child node to remove * * @throws NoSuchElementException if <var>child</var> is not a child of this * node */ void removeChild(final TreeList<E> child); /** * Removes the child node at the given <var>index</var> position from this * node, and returns it. Afterwards, the returned node is a <em>root * node</em>. * * @param index the child position, 0-based * * @return the removed node * * @throws IndexOutOfBoundsException if <var>index</var> is negative or * larger than the count of children of this node */ TreeList<E> removeChild(final int index); /** * Removes the children nodes in the given collection, <var>c</var>. * * @param c the child nodes to remove * * @return {@code true} if the tree changed as a result of this call */ boolean removeAllChildren(final Collection<TreeList<E>> c); /** * Removes all but the children nodes in the given collection, * <var>c</var>. * * @param c the child nodes to retain * * @return {@code true} if the tree changed as a result of this call */ boolean retainAllChildren(final Collection<TreeList<E>> c); /** * Gets the value of this node. Ordinary {@code List} operations behave as * if they were operation on a list of node values. * * @return the node value */ E getValue(); /** * Sets the value of this node to the given <var>value</var>. Ordinary * {@code List} operations behave as if they were operation on a list of * node values. * * @param value the new value */ void setValue(final E value); }
An implementation to follow in a later post.
No comments:
Post a Comment