Sometimes you want to insert elements of different types into a tree set. The elements may not be instances of java.lang.Comparable . You can define a comparator to compare these elements. To do so, create a class that implements the java.util.Comparator interface. The Comparator interface has two methods , compare and equals .
public int compare(Object element1, Object element2)
Returns a negative value if element1 is less than element2 , a positive value if element1 is greater than element2 , and zero if they are equal
public boolean equals(Object element) .
Returns true if the specified object is also a comparator and imposes the same ordering as this comparator.
Note
The equals method is also defined in the Object class. Therefore, you will not get a compilation error even if you don't implement the equals method in your custom comparator class. However, in some cases implementing this method may improve performance by allowing programs to determine quickly whether two distinct comparators impose the same order. |
Listing 22.4 declares a Comparator for geometric objects. The GeometricObject class was introduced in §10.2, "Abstract Classes." Line 4 implements Comparator<GeometricObject> . Line 5 overrides the compare method to compare two geometric objects. The comparator class also implements Serializable . It is generally a good idea for comparators to implement Serializable , as they may be used as ordering methods in serializable data structures such as TreeSet . In order for the data structure to serialize successfully, the comparator (if provided) must implement Serializable .
1 import java.util.Comparator; 2 3 public class GeometricObjectComparator 4 implements Comparator<GeometricObject> , java.io.Serializable { 5 public int compare(GeometricObject o1, GeometricObject o2) { 6 double area1 = o1.getArea(); 7 double area2 = o2.getArea(); 8 9 if (area1 < area2) 10 return -1 ; 11 else if (area1 == area2) 12 return ; 13 else 14 return 1 ; 15 } 16 } |
If you create a TreeSet using its no-arg constructor, the compareTo method is used to compare the elements in the set, assuming that the class of the elements implements the Comparable interface. To use a comparator, you have to use the constructor TreeSet(Comparator comparator) to create a sorted set that uses the compare method in the comparator to order the elements in the set.
Listing 22.5 gives a program that demonstrates how to sort elements in a tree set using the Comparator interface. The example creates a tree set of geometric objects in lines 6 “7. The geometric objects are sorted using the compare method in the Comparator interface. The output of the program is shown in Figure 22.8.
1 import java.util.*; 2 3 public class TestTreeSetWithComparator { 4 public static void main(String[] args) { 5 // Create a tree set for geometric objects using a comparator 6 Set<GeometricObject> set = 7 new TreeSet<GeometricObject>( new GeometricObjectComparator()); 8 set.add( new Rectangle( 4 , 5 )); 9 set.add( new Circle( 40 )); 10 set.add( new Circle( 40 )); 11 set.add( new Rectangle( 4 , 1 )); 12 13 // Display geometric objects in the tree set 14 System.out.println( "A sorted set of geometric objects" ); 15 for (GeometricObject element: set) 16 System.out.println( "area = " + element.getArea()); 17 } 18 } |
The Circle and Rectangle classes were defined in §10.2, "Abstract Classes." They are all subclasses of GeometricObject .
Two circles of the same radius are added to the set in the tree set (lines 9 “10), but only one is stored, because the two circles are equal and the set does not allow duplicates.
Note
Comparable is used to compare two objects of the same type, but Comparator can be used to compare two objects of different types. |