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