How to use Comparator in Java to sort
There are a couple of awkward things with your example class:
- it's called People while it has a
price
andinfo
(more something for objects, not people); - when naming a class as a plural of something, it suggests it is an abstraction of more than one thing.
Anyway, here's a demo of how to use a Comparator<T>
:
public class ComparatorDemo { public static void main(String[] args) { List<Person> people = Arrays.asList( new Person("Joe", 24), new Person("Pete", 18), new Person("Chris", 21) ); Collections.sort(people, new LexicographicComparator()); System.out.println(people); Collections.sort(people, new AgeComparator()); System.out.println(people); }}class LexicographicComparator implements Comparator<Person> { @Override public int compare(Person a, Person b) { return a.name.compareToIgnoreCase(b.name); }}class AgeComparator implements Comparator<Person> { @Override public int compare(Person a, Person b) { return a.age < b.age ? -1 : a.age == b.age ? 0 : 1; }}class Person { String name; int age; Person(String n, int a) { name = n; age = a; } @Override public String toString() { return String.format("{name=%s, age=%d}", name, age); }}
EDIT
And an equivalent Java 8 demo would look like this:
public class ComparatorDemo { public static void main(String[] args) { List<Person> people = Arrays.asList( new Person("Joe", 24), new Person("Pete", 18), new Person("Chris", 21) ); Collections.sort(people, (a, b) -> a.name.compareToIgnoreCase(b.name)); System.out.println(people); Collections.sort(people, (a, b) -> a.age < b.age ? -1 : a.age == b.age ? 0 : 1); System.out.println(people); }}
Here's a super short template to do the sorting right away :
Collections.sort(people,new Comparator<Person>(){ @Override public int compare(final Person lhs,Person rhs) { //TODO return 1 if rhs should be before lhs // return -1 if lhs should be before rhs // return 0 otherwise (meaning the order stays the same) } });
if it's hard to remember, try to just remember that it's similar (in terms of the sign of the number) to:
lhs-rhs
That's in case you want to sort in ascending order : from smallest number to largest number.
Use People implements Comparable<People>
instead; this defines the natural ordering for People
.
A Comparator<People>
can also be defined in addition, but People implements Comparator<People>
is not the right way of doing things.
The two overloads for Collections.sort
are different:
<T extends Comparable<? super T>> void sort(List<T> list)
- Sorts
Comparable
objects using their natural ordering
- Sorts
<T> void sort(List<T> list, Comparator<? super T> c)
- Sorts whatever using a compatible
Comparator
- Sorts whatever using a compatible
You're confusing the two by trying to sort a Comparator
(which is again why it doesn't make sense that Person implements Comparator<Person>
). Again, to use Collections.sort
, you need one of these to be true:
- The type must be
Comparable
(use the 1-argsort
) - A
Comparator
for the type must be provided (use the 2-argssort
)
Related questions
Also, do not use raw types in new code. Raw types are unsafe, and it's provided only for compatibility.
That is, instead of this:
ArrayList peps = new ArrayList(); // BAD!!! No generic safety!
you should've used the typesafe generic declaration like this:
List<People> peps = new ArrayList<People>(); // GOOD!!!
You will then find that your code doesn't even compile!! That would be a good thing, because there IS something wrong with the code (Person
does not implements Comparable<Person>
), but because you used raw type, the compiler didn't check for this, and instead you get a ClassCastException
at run-time!!!
This should convince you to always use typesafe generic types in new code. Always.