Most read:
Popular archives:
JavaWorld's new look is here!
We've upgraded the site with a fresh look-and-feel, improved topical navigation, better search, new features, and expanded
community platform. Learn more about the changes to JavaWorld.
| Oracle Compatibility Developer's Guide |
| The Explosion in DBMS Choice |
A String object was used because it has the property of being easily sorted. No other standard object in the Java standard libraries is both as flexible and as sortable as a string. We can't go ahead and make all keys in our container a subclass of String because String is final -- it can't be subclassed. Further, some objects work well as their own key, that can save space on the heap and garbage generation, both of which are Good Things. So what do we do? Well, let's see...
There are three approaches to solving the key dilemma. Each has its drawbacks, so one might conclude that there is no good solution. This is not true. A good universal solution may not exist, but there are widely applicable solutions.
The first approach takes advantage of the fact that every object defines a toString method. This method is initially defined in Object but can be overridden by subclasses.
The toString method was designed so that all objects might have some representation that could be displayed on a character device such
as a terminal or window. The number classes provide overridden versions that convert a subclass of Number to a printable representation. The default implementation in Object gives you the name of the object's class and its reference
number (actually its address in memory) as a string. The format of the string is classname@hex-address.
With this knowledge, we can write a helper method -- stringForKey -- and then rewrite get, put, and remove to use this method on the key objects that are passed to them. The next bit of code shows both the helper method and the
rewritten get that implements this solution:
private String stringForKey(Object o) {
if (o instanceof String)
return (String) o;
return o.toString();
}
public Object get(Object skey) {
String s = stringForkey(skey);
return search(rootNode, s).payload;
}
In the code above, this version of the method uses the instanceof operator in Java to test if the key passed is already a string; if it isn't, it uses the toString method in Object to create a string for the tree. I have included a link to the source code of BinarySearchTree written in this way.
The advantage here is that, by default, all objects have an implementation of toString, and if this method is implemented in such a way as to uniquely define objects, we could certainly use it. Unfortunately,
this solution depends on Java programmers knowing that this function may be used for this purpose. If a naive programmer were
to design a class with an override of toString like that shown below, our search tree would be in big trouble.