Comparable/Comparator Interfaces Topics: Comparable and Comparator interfaces in JCF “Java Collections Framework” Function objects 1
Back to Java: Comparable / Comparator In computing, we often want to order a set of items Find the max/best or min/worst Sort them in order Note how this is different than what is needed for search (where we just need equals) Need a way to compare two items Want a flexible way to “compare” using different criteria In Java, let’s us use Collection(s) methods to meet our own special needs. ( Powerful !) 2
Check out the Collections class Class C ollections utility methods for doing operations on Collections, Lists (that almost always contain homogenous elements) Note very similar Arrays class See MSD textbook, Section 9.5, pp. 666f Methods (static, mostly for Lists) search a list for an item: binarySearch () sort(), max(), min() -- uses compareTo () or Comparator object reverse(), fill(), shuffle(), copy(), replaceAll () List list2 = Collections.unmodifiableList (list1); // p. 668 3
Comparable Interface First solution: Can we ask an object how it compares to a second object? Sure: string1.compareTo(string2) Programming convention: Return value as follows: zero if the same negative value if first item strictly less than second positive value if first item strictly greater than second Java provides a Comparable interface int compareTo ( YourClass o) Note the parameter is an object of the same type as the class in which you’re defining compareTo () 4
Hang on: What’s an Interface? When defining a class, state that it “implements” an interface. E.g. public class Watch implements TimeKeeper { What else is the meaning of the interface TimeKeeper ? A set of methods that any implementing class must include TimeKeeper interface doesn’t define how these methods are coded Watch (the implementing class) is promising to include those in its definition 5
Example A TimeKeeper Interface defined with its 2 methods: getTime () and set Time() Now a Watch class is declared to implement TimeKeeper Watch is promising to have these 2 methods as part of its definition ( getTime () and setTime ()) Watch can implement those how ever it wants It means Watch, by implementing TimeKeeper , can handle the TimeKeeper role 6
Interface gives an Object another Type With this definition: public class Watch implements TimeKeeper { You can think of Watch in these ways: You can treat a Watch object as a TimeKeeper A Watch object can do “ TimeKeeper things” A Watch object can be used anywhere a TimeKeeper is legal to use A Watch object has more than one type It’s a Watch (defined by the class Watch) It’s a TimeKeeper (defined by the interface) 7
Interface gives an Object another Type Interfaces are legal Java types. Therefore can be used To declare variables As a parameter type (passing a variable to a method) As a return type 8
Example If you have a method that took a TimeKeeper as a parameter A Watch could be used as a parameter to that method, because a Watch plays the role of a TimeKeeper If that method takes a TimeKeeper as a parameter, then we can pass it a Watch You can think of the Watch object as having more than one type. (Every Watch also fills the role as Time Keeper) 9
What are we getting at? The method sort can take an ArrayList as an argument (an ArrayList of something) Of what? It can take an ArrayList of anything that meets this interface called Comparable The parameter has to be an ArrayList of any class that implements the comparable interface – that means it has the compareTo () method – which means inside of sort , it knows it can call get() to get 2 items from the ArrayList and use the compareTo () method – its guaranteed to have it because that class implements the Comparable interface 10
Writing compareTo for Your Classes If you ever want to put your own objects in Collections, and use sort(), max(), min(),… Make your class implement Comparable Implement the compareTo () method in your class How to write compareTo ()? Think about state-variables that determine natural order Compare them and return proper-value Note: For number values, you can subtract. For object values, call compareTo () on them. 11
Let’s Get Practical You can sort an ArrayList … BUT the ArrayList has to have things inside it that implement the Comparable Interface Can we sort an ArrayList of Strings ? Go to API for class String ( Google: “java api string”) On “All Implemented Interfaces” – one of them is comparable! Scroll to “Method Summary” – has compareTo () method! So you can definitely sort an ArrayList of Strings 12
Example: Writing compareTo() Imagine something like an entry in a phonebook Order by last name, first name, then number int compareTo ( PhoneBookEntry item2 ) { int retVal = last.compareTo (item2.last); if ( retVal != 0 ) return retVal ; retVal = first.compareTo (item2.first); if ( retVal != 0 ) return retVal ; retVal = phNum - item2.phNum; return retVal ; } 13
See Example done in class ECLIPSE EXAMPLE 14
Under the Hood for Sorting How might a sort() or any other method use this? Imagine: Its parameter is of the type List<Comparable> ArrayList is a type-of List in Java (more on this later) Inside a loop, code might look like this: Comparable item1 = theList.get ( i ); Comparable item2 = theList.get (j); int cmpResult = item1.compareTo(item2); Such code will work when the list stores any class that implements Comparable! But, what happens if list-elements are of different classes (still Comparable, but different)? compareTo () fails! 15
Flexible Design using Comparators Solution #1: Make classes Comparable Disadvantage: just one way to compare is possible, because there’s just one compareTo method per class Possible solutions: Separate functions: sortByName (), sortByNum (),… We can’t predict in advance how you’ll want to sort! Pass a parameter to indicate control: sort( theList , “ byName ”) or sort( theList , “ byNum ”); Ugh. Same problem as before And the internals of sort() will grow to become very ugly 16
Function Objects We need to somehow pass “how to execute” information as a parameter to sort() We pass objects as parameters Can we pass a method/operation as an object? Many languages support this, but in different ways: C and C++ – pointers to functions C# – delegates Java – “function objects” that implement a specified interface, and the one method in that interface does the needed work 17
Function Objects in Java Idea: encapsulate a function inside a class Note: not our usual idea of a class State? (None.) Identity? (Just need one instance.) Represents an entity? (Nope! Just a place to stash a function so it can be passed as a parameter.) Warning / caveat! This idea is contrary to many OO principles, but… Useful if done in limited circumstances Use it when the libraries make it available Not often part of your own class-design But use it in libraries when it’s part of the framework 18
Example: Comparator objects We want to pass a function-object to a method: Collections.sort ( someList , function-object-goes-here); But what type should this object be? Use an Interface: Interface name can be used as a type in the parameter list Interface defines the method name itself! 19
Example: Comparator objects Java’s Comparator interface: int compare ( Object o1, Object o2); Notes: not compareTo ()! Takes two parameters! Define a class for each kind of comparison you want. E.g. Classes: CmpStudentByGpa , CmpStudentByGpaDesc Classes: CmpDogByName , CmpDogByBreed 20
Writing a Comparator Class Example like one from MSD text, p. 647 We have a Dog class with name, breed and gender Compare two doggies by breed and then name public class CmpDogByBreedAndName implements Comparator<Dog> { public int compare (Dog d1, Dog d2) { int retVal = d1. getBreed() . compareTo (d2. getBreed() ) ; if ( retVal != 0 ) return retVal ; return d1.getName(). compareTo ( d2.getName() ); } } 21
Use of Comparator methods How to use with Collections.sort () ArrayList dogList = …; Collections.sort ( dogList , new CmpDogByName () ); Collections.sort ( dogList , new CmpDogByBreed () ); (Do you understand what new does here?) Inside sort (), code looks something like this: sort ( List theList , Comparator cmpObj ) { // in some loop Object item1 = list.get ( i ); Object item2 = list.get (j); cmpResult = cmpObj .compare (item1,item2); 22
End of Comparable/Comparator topics Keep these techniques in mind as we move forward 23
Java Aside: Anonymous Classes There’s a Java technique called anonymous classes One of several types of nested class definition You’ll very often see it in GUI programming (Swing) and with threads Situation: Sometimes Java’s design encourages us to create some thing that might be used just once That thing needs to be wrapped up in a class, say because we need a function object 24
Creating and Using an Anonymous Class Example: sort a list of Strings by their length Collections.sort ( stringList , new Comparator() { public int compare ( Object o1, Object o2 ) { return ((String) o1).length() – ( (String) o2).length(); } } ) ; We’ve created a new Comparator “ on the fly ” new creates a new instance, but what kind? Some object that implements Comparator Object not named , and its “true” class not named ! What must a Comparator have? compare () We defined it right here, where it’s used! 25
Anonymous Classes: Comments Anonymous classes are unlike other classes They have no name Typically only implement methods in their interface or superclass. No new methods! Since they have no name, can only define and use them at one point in your code! Hard to understand at first? Sure! Naming an abstraction is important for human understanding! Sorting, a Collection, Comparing Advice Keep them very short (and simple)! Be ready to understand them when you see them in Swing and with threads 26