12. Arrays and Array Processing

12.9. OBJECT-ORIENTED DESIGN: Polymorphic Sorting (Optional)

One limitation of the sort routines developed so far is that they only work on one particular type of data. If you’ve written an insertion sort to sort ints, you can’t use it to sort doubles. What would be far more desirable is a polymorphic sort method—that is, one method that could sort any kind of data. This is easily done by making use of Java wrapper classes, such as Integer and Double, together with the java.lang.Comparable interface, which is specially designed for this purpose.

The java.lang.Comparable interface consists of the compareTo() method:

,,

 

 

J

By implementing compareTo(), a class can impose an order on its ob-

jects. The Comparable interface is implemented by all of Java’s wrapper

classes—that is, by Integer, Double, Float, Long, and so on (Fig. 9.24).

 

Figure 9.24: Java wrapper classes, such as Integer and Double, implement the Comparable in- terface.


As we saw in Chapter 8, Java interfaces allow us to create a form of mul- tiple inheritance. For example, as Figure 9.24 shows, an Integer is both an Object and a Comparable. One implication of this is that an Integer can be used in any method that takes either an Object parameter or a Comparable parameter.

The compareTo() method takes an Object parameter and returns an int. It is meant to be invoked as o1.compareTo(o2), where o1 and o2 are objects of the same type. Classes that implement compareTo() must abide by the following rules for its return value:

,,

 

 

 

J

In other words, if o1 < o2, then o1.compareTo(o2) will return a neg- ative integer. If o1 > o2, then o1.compareTo(o2) will return a posi-

 

SECTION 9 OOD: Polymorphic Sorting429

tive integer. And if o1 and o2 are equal, then o1.compareTo(o2) will return 0.

For a class that implements Comparable, we can use the compareTo() method to help sort its elements. For example, the following revised version of insertionSort() method can be used to sort any array of Comparable objects—that is, any array of objects whose class imple- ments Comparable:

,,

 

 

 

 

 

 

 

J

In this version, the parameter is an array of Comparable. Thus, we can pass it any array whose elements implement Comparable, including an array of Integer or Float, and so on. Then, to compare elements of a Comparable array, we use the compareTo() method:

,,

 

J

Note that our algorithm no longer refers to ints, as in the original in- sertion sort. Indeed, it doesn’t mention the specific type—Integer, Float, or whatever—of the objects that it is sorting. It refers only to Comparables. Therefore, we can use this method to sort any type of object, as long as the object’s class implements the Comparable interface. Thus, by using Comparable, we have a more general insertionSort() method, one that can sort any one-dimensional array of Comparables.

The TestSort class (Figs. 9.25 and 9.26) provides an example of how

to use the polymorphic sort() method.

It contains three methods: The sort() method that we just described;

a polymorphic print() method, which can be used to print the val-

 

ues of any array of Comparable; and a main() method. The main() method creates arrays of Integer and Float and then uses the poly- morphic sort() method to sort them. Note how the print() method uses the polymorphic toString() method to print the elements of a Comparable array.

This example of polymorphic sorting illustrates once again the great

power of inheritance and polymorphism in object-oriented programming. The Integer and Float classes use class inheritance to inherit features from the Object class, and they use interface implementation to inherit the compareTo() method from the Comparable class. By implement- ing versions of the toString() and compareTo() methods that are ap- propriate for these wrapper classes, Java makes it easier to use Integer and Float objects in a variety of contexts. Taken together, inheritance


Figure 9.25:The TestSort()

class.

 

and polymorphism enable us to design very general and extensible algo- rithms. In this example, we defined a sort() method that can sort an array containing any kind of object as long as the object implements the Comparable interface.

The java.util.Arrays.sort() Method

While sorting algorithms provide a good way to introduce the concepts of array processing, real-world programmers never write their own sort algorithms. Instead they use library methods, which have been writ- ten and optimized by programming experts. Moreover, library sort rou- tines use sort algorithms that are much more efficient than the ones we’ve discussed.

The java.util.Arrays class contains a polymorphic sort method that is very simple to use. For example, here’s how we would use it to sort the two arrays declared in the TestSort program:

,,

 

 

 

 

 

Vector

 

+Vector()

+Vector(in size : int)

+addElement(in o : Object)

+elementAt(in index : int) : Object

+insertElementAt(in o : Object, in x : int)

+indexOf(in o : Object) : int

+lastIndexOf(in o : Object) : int

+removeElementAt(in index : int)

+size() : int

 

Figure9.27:The

java.util.Vectorclass.

 

 

 

 

java.sun.com/j2se/1.5.0/docs/api/


J

That’s all there is to it! Obviously, learning how to use Java’s class and method library, saves real-word programmers lots of effort.

SELF-STUDY EXERCISES

EXERCISE 9.20 Add a definition of a compareTo() method to the LetterFreq class so that it implements the Comparable interface. The method should define one object to be less than another object if its freq instance variable is less.

EXERCISE 9.21 Add a definition of a sort() method that can be added to the definition of the AnalyzeFreq class. Make it so the array in the class can be sorted into ascending order using the or- dering of LetterFreq defined in the previous exercise. Use the java.util.Arrays.sort() method.

EXERCISE 9.22 Rewrite the main() of the AnalyzeFreq class to make use of the sort() method of the previous exercise.