Comparators

Comparing Instances of a Class

In the Warmup of Lab 7, we explored the use of Java’s Comparable<T> interface requiring a class T to implement a public int compareTo(T other) method that compares the current instance with another instance of the class and returns:

  • returns a negative number if this is less than other
  • returns 0 if this is equal to other
  • returns a positive number if this is greater than other

This approach is really useful if we need to determine an ordering on instances of a class, for example if we need to sort objects of that class. However, a class can only implement one version of the compareTo method. So this approach works well if we have only one way that we want to be able to compare two instances of the class.

Multiple Comparisons (Comparator Interface)

What then should we do if we want to be able to compare complex classes based on more than type of comparison? For example, in our running Contact class example that stores the office locations for Oberlin staff and faculty, we might want to be able to compare two Contacts either by the peoples’ names or by their office locations.

As an alternative in Java, we can instead create Comparator<T> classes whose sole purpose is to be able to implement a new type of comparison between two instances of class T. For example, we could create one NameComparator implements Comparator<Contact> class that compares two Contact instances based on their name, and a second OfficeComparator implements Comparator<Contact> that compares two Contact instances based on their office location.

Classes that implement the Comparator<T> interface only need to implement a single method public int compare(T first, T second) that behaves very similar to the compareTo method from the Comparable<T> interface – the compare method should return:

  • returns a negative number if first is less than second
  • returns 0 if first is equal to second
  • returns a positive number if first is greater than second

The compare method should be consistent so that if the roles of first and second are flipped, the opposite values are returned (or 0 if they are equal).

Comparing Two Contacts

As in the Warmup of Lab 7, we have provided you with an implementation of the Contact class in the file Contact.java, which also has some test code commented out in its main method.

Your first task in this warmup exercise is to implement a new class NameComparator that implements Comparator<Contact> and has a compare method that compares two Contract instances by their name instance variable (which can be looked up using the getName() method). This class should be implemented in a file NameComparator.java. Similar to Lab 7, the method should:

  • return a negative number if first.name is earlier in the alphabet than second.name
  • return 0 if first.name is the same as second.name
  • return a positive number if first.name is later in the alphabet than second.name

Hint

You could consider using the String class’s compareTo method here to implement your solution once you have the two Strings. You can also look at the provided AvailableComparator.java class for hints about the general structure of a Comparator class.

To test whether your solution has worked, you can uncomment the first eight lines of actual code in the main function (by deleting the first two comment lines that include [REMOVE THIS LINE TO TEST]). You should check whether negative, 0, or positive numbers are printed for the three print statements for the two Contact objects. Note: this code should output the same values are the analogous code in the Warmup of Lab 7

Your second task in this warmup exercise is implement a second new class OfficeComparator that also implements Comparator<Contact> and has a compare method that compares two Contact instances based on their office instance variable (that can be looked up using the getOffice() method). This class should be implemented in a file OfficeComparator.java. Similar to NameComparator, this method should:

  • return a negative number if first.office is earlier in the alphabet than second.office
  • return 0 if first.office is the same as second.office
  • return a positive number if first.office is later in the alphabet than second.office

Finally, you should predict what will happen if you uncomment the remaining code in the main function (by deleting the last two comment lines that include [REMOVE THIS LINE TO TEST]). In particular, you should predict what you think will be printed and write your prediction in a new text file called contact_prediction.txt. Then run the code and see if your prediction came true. If not, try to think about what caused the result instead. Note: this will not be exactly the same as in the Warmup of Lab 7 since we sort the list twice.

Don’t forget to add/commit/push your NameComparator.java, OfficeComparator.java, and contact_prediction.txt files.