class Person implements Comparable<Person>{
int age;
String name;
String email;
@Override
public int compareTo(Person o) {
return name.compareTo(o.getName());
}
}
Comparable vs Comparator in Java
Upasana | August 14, 2020 | 3 min read | 350 views
Both comprabale and comparator are interfaces from Java Collections Framework that allow sorting of collections. But both of these interfaces are meant for different purpose.
Comparable | Comparator |
---|---|
Imposes a total ordering on the objects of each class that implements it. This ordering is referred to as class’s natural ordering, and the class’s |
It is a comparison function, which imposes a total ordering on some collection of objects. |
Comparable provides only single sorting sequence (based on single or multiple fields) |
N number of comparators can be created for different sorting sequences |
Comparable affects the original class |
Unlike |
Comparable provides |
Comparator provides |
It is part of |
It is part of |
|
This function can be passed to |
It is strongly recommended that natural ordering be consistent with equals, else sorted set and sorted map will behave strangely. Virtually all Java classes that implement |
No such requirements |
Example Code
Lets take a concrete example of Comparable and Comparator
Now we can sort a collection of persons based on its natural ordering using Collections.sort
method.
List<Person> students = Arrays.asList(
new Person(20,"Bob", "bob@mail.com"),
new Person(19, "Jane", "Jane@mail.com"),
new Person(21,"Foo", "foo@mail.com")
);
Collections.sort(students);
This program will always sort persons based on their name i.e. Bob → Foo and thenJane.
Lets define two comparators now, one for name based comparison and another on basis of age.
class NameComparator implements Comparator<Person> {
@Override
public int compare(Person o1, Person o2) {
return o1.name.compareTo(o2.name);
}
}
class AgeComparator implements Comparator<Person> {
@Override
public int compare(Person o1, Person o2) {
return ((Integer)o1.age).compareTo(o2.age);
}
}
Now we can specify one of the above defined sorting function to choose sorting on demand:
List<Person> students = Arrays.asList(
new Person(20,"Bob"),
new Person(19, "Jane"),
new Person(21,"Foo")
);
Collections.sort(students, new AgeComparator());
Eay enough?
Chaining of comparison operations in Java 8
Java 8’s lambda expressions brings syntax improvements to sorting capabilities of Java Collections Framework. We can even chain multiple sorting operations using chaining of operations, as shown in below code:
List<Person> students = Arrays.asList(
new Person(20,"Foo"),
new Person(19, "Jane"),
new Person(21,"Foo")
);
Collections.sort(students);
students.stream()
.sorted(Comparator
.comparing(Person::getName)
.thenComparing(Person::getAge)
).forEach(System.out::println);
Even reverse sort is easy enough:
students.stream()
.sorted(Comparator
.comparing(Person::getName)
.thenComparing(Person::getAge)
.reversed() (1)
).forEach(System.out::println);
1 | Sorting Age in reverse direction. reversed() Returns a comparator that imposes the reverse ordering of this comparator. |
Case insensitive ordering
For certain fields like email, case does not matter. Its easy to achieve this using Java 8:
students.stream()
.sorted(Comparator
.comparing(Person::getName)
.thenComparing(Person::getAge)
.thenComparing(Person::getEmail, Comparator.nullsLast(String.CASE_INSENSITIVE_ORDER))
).forEach(System.out::println); (1)
1 | null values are pushed to last |
Top articles in this category:
- Fail-Safe vs Fail-Fast Iterator in Java Collections Framework
- Http download using Java NIO FileChannel
- Java 8 Parallel Stream custom ThreadPool
- How will you increment each element of an Integer array, using parallel operation
- What are four principles of OOP, How aggregation is different than Composition?
- Troubleshooting Deadlock in Java
- What is AtomicInteger class and how it works internally