Why does the Java Collections Framework offer two different ways to sort?
If I have a list of elements I would like to sort, Java offers two ways to go about this.
For example, lets say I have a list of Movie objects and I’d like to sort them by title.
One way I could do this is by calling the one-argument version of the static java.util.Collections.sort( ) method with my movie list as the single argument. So I would call Collections.sort(myMovieList). In order for this to work, the Movie class would have to be declared to implement the java.lang.Comparable interface, and the required method compareTo( ) would have to be implemented inside this class.
Another way to sort is by calling the two-argument version of the static java.util.Collections.sort( ) method with the movie list and a java.util.Comparator object as it’s arguments. I would call Collections.sort(myMovieList, titleComparator). In this case, the Movie class wouldn’t implement the Comparable interface. Instead, inside the main class that builds and maintains the movie list itself, I would create an inner class that implements the java.util.Comparator interface, and implement the one required method compare( ). Then I'd create an instance of this class and call the two-argument version of sort( ). The benefit of this second method is you can create an unlimited number of these inner class Comparators, so you can sort a list of objects in different ways. In the example above, you could have another Comparator to sort by the year a movie was made, for example.
My question is, why bother to learn both ways to sort in Java, when the two-argument version of Collections.sort( ) does everything the first one-argument version does, but with the added benefit of being able to sort the list’s elements based on several different criteria? It would be one less thing to have to keep in your mind while coding. You’d have one basic mechanism of sorting list开发者_如何转开发s in Java to know.
One is for conciseness for what should be a common case (Effective Java 2nd Edition, Item 12: Consider implementing Comparable
). The other, as you noted, is for flexibility and general-purposeness.
Related questions
- difference between compare() and compareTo()
- When to use Comparable vs Comparator
- Comparable and Comparator contract with regards to null
- Can I use a Comparator without implementing Comparable?
It depends who controls the ordering. If the ordering of an object is an implementation detail of the object, the Comparable
is more appropriate. If the ordering of the objects is controlled by the caller, then Comparator
is more appropriate.
I'm not sure I find it that odd. I have a list of things to sort that have a natural order like numbers. Do I really expect I have to tell the API how to compare numbers? I wouldn't look for a two-arg method, intuitively. Thus Comparable exists.
But of course you can and should be able to define a different ordering, thus the other method. For example, even though numbers have a natural ordering, I may still want a different ordering: for example, order by value descending. Thus Comparator exists.
And of course some things don't have a natural ordering like Fruit, but you might still wish to order a list of them. Thus Comparator, again.
精彩评论