Hi Brendon, here for the nitpicking again :P
-
You should make your class declaration
class Tree<T extends Comparable<? super T>>. The reason for this is that if you have a class that knows how to compare its instances, you can also create Trees of its subclasses. Let's say you have a
class Fruit implements Comparable<Fruit>, and a
class Pear extends Fruit. With your old class header, you won't be able to create a
Tree<Pear>, because
Pear does not extend
Comparable<Pear>.
- Your root node should have the same type parameter as your tree:
private TreeNode<T>.
- A
TreeNode intrinsically belongs to a specific
Tree. Don't make the class static. That way, you can even navigate back to the root from any node with
Tree.this.root.
- The
findHeight() methods have a type parameter. They don't need one, because they're not concerned with any element types to find the height of a tree.
- Your recursive
findHeight() method doesn't use context (it only operates on the passed argument) so it can be static.
- The
insert() and
insertNode() methods don't need type parameters. They use the same type arguments as the
Tree class. This will likely solve your unchecked problems (in combination with using a properly typed root).
- Your
Tree class is not final, but you do define a bunch of final methods on it. It looks like you are designing for inheritance. You should consider overriding
clone() to facilitate sub-classes that might want to implement
Cloneable, you should consider implementing
equals() and
hashCode() and make them final, or specify what they do in a method stub with a contract. You're also not allowing sub-classes the opportunity to define more efficient implementations of
findHeight() or
insertNode().