When to use comparable and comparator interfaces in java

You must have been came across the situation where you have to sort a collection of objects by a certain rule. And if you are working on a domain where people are your main entities, you will encounter it more. There must be many ways to it, which ranges from sorting on client UI using javascript to sorting on server side using complex algorithm, and sometimes in database too.

If you do not have millions of records to play with at a time then for sorting i will recommend you to consider comparable or comparator interface.

Sections in this post:

  • Defining Employee class
  • Implementing Comparable interface and Testing our code
  • What if we want to sort on different fields??
  • Adding different Comparator interface implementations
  • Testing our code
  • Understanding uses in other core collection classes
  • Caution words

Defining Employee class

Our employee class is plain old class with four fields: id, firstName, lastName and age. I have chosen these fields purposefully. We will see usage later in this post.

01. package corejava.compare;
02.  
03. public class Employee {
04. private int id = -1;
05. private String firstName = null;
06. private String lastName = null;
07. private int age = -1;
08.  
09. public Employee(int id, String fName, String lName, int age) {
10. this.id = id;
11. this.firstName = fName;
12. this.lastName = lName;
13. this.age = age;
14. }
15.  
16. @Override
17. public String toString() {
18. return "Employee : " + id + " - " + firstName + " - " + lastName
19. + " - " + age + "n";
20. }
21.  
22. public int getId() {
23. return id;
24. }
25.  
26. public void setId(int id) {
27. this.id = id;
28. }
29.  
30. // Other accessor methods here
31. }

Implementing Comparable interface and Testing our code

Comparable interface provides one method compare(Object o) to implement in any class so that two instances of that class can be compared. Signature of method is:

1. public int compareTo(T o);

Here, out of two instances to compare, one is instance itself on which method will be invoked, and other is passed as parameter o.

Lets see how our Employee class will look after implementing Comparable interface.

01. package corejava.compare;
02.  
03. public class Employee implements Comparable<employee> {
04. private int id = -1;
05. private String firstName = null;
06. private String lastName = null;
07. private int age = -1;
08.  
09. public Employee(int id, String fName, String lName, int age) {
10. this.id = id;
11. this.firstName = fName;
12. this.lastName = lName;
13. this.age = age;
14. }
15.  
16. @Override
17. public int compareTo(Employee o) {
18. return this.id - o.id;
19. }
20.  
21. @Override
22. public String toString() {
23. return "Employee : " + id + " - " + firstName + " - " + lastName
24. + " - " + age + "n";
25. }
26.  
27. public int getId() {
28. return id;
29. }
30.  
31. public void setId(int id) {
32. this.id = id;
33. }
34.  
35. // Other accessor methods
36. }

Default way to sort a list of employees, in our case, is by their id. Whatever, your default sorting order is, use in compare() method.
In implemented compare() method, we have simply returned the difference in employee ids of two instances. Two equal employee ids will return zero, indicating same object.

Lets test our compare() method.

01. package corejava.compare;
02.  
03. import java.util.ArrayList;
04. import java.util.Collections;
05. import java.util.List;
06.  
07. public class TestSorting {
08. public static void main(String[] args) {
09. Employee e1 = new Employee(1, "aTestName", "dLastName", 34);
10. Employee e2 = new Employee(2, "nTestName", "pLastName", 30);
11. Employee e3 = new Employee(3, "kTestName", "sLastName", 31);
12. Employee e4 = new Employee(4, "dTestName", "zLastName", 25);
13.  
14. List</employee><employee> employees = new ArrayList</employee><employee>();
15. employees.add(e2);
16. employees.add(e3);
17. employees.add(e1);
18. employees.add(e4);
19.  
20. // UnSorted List
21. System.out.println(employees);
22.  
23. Collections.sort(employees);
24. // Default Sorting by employee id
25. System.out.println(employees);
26. }
27. }

In above program, first print statement prints an unsorted list of employees and in second print statement, employees are sorted by their employee id.

What if we want to sort on different fields??

So, now we can sort a collection of employees by their id. Now lets consider a case where we want to sort employees list based on some user input which is essentially sorting field i.e. sometime he want to sort by first name, sometimes by even age also.

This can be achieved by jquery plugins easily, but what if browser has disables the java script. You will have to sort the list on server side only to not break the application functionality.

Here comes the Comparators to rescue you. A comparator can be used to sort a collection of instances on some particular basis. To sort of different fields, we need multiple comparators.

Adding different Comparator interface implementations

As discussed in last section, we need to have multiple implementations for different sorting cases. Lets write them one by one:

First name sorter

01. package corejava.compare;
02.  
03. import java.util.Comparator;
04.  
05. public class FirstNameSorter implements Comparator</employee><employee>{
06.  
07. @Override
08. public int compare(Employee o1, Employee o2) {
09. return o1.getFirstName().compareTo(o2.getFirstName());
10. }
11. }

Last name sorter

01. package corejava.compare;
02.  
03. import java.util.Comparator;
04.  
05. public class LastNameSorter implements Comparator</employee><employee> {
06.  
07. @Override
08. public int compare(Employee o1, Employee o2) {
09. return o1.getLastName().compareTo(o2.getLastName());
10. }
11.  
12. }

Age sorter

01. package corejava.compare;
02.  
03. import java.util.Comparator;
04.  
05. public class AgeSorter implements Comparator</employee><employee> {
06. @Override
07. public int compare(Employee o1, Employee o2) {
08. return o1.getAge() - o2.getAge();
09. }
10. }

Testing our code

So theoretically, we should be able to sort of any field at our wish with minimum code. Lets see if we really are:

01. package corejava.compare;
02.  
03. import java.util.ArrayList;
04. import java.util.Collections;
05. import java.util.List;
06.  
07. public class TestSorting {
08. public static void main(String[] args) {
09. Employee e1 = new Employee(1, "aTestName", "dLastName", 34);
10. Employee e2 = new Employee(2, "nTestName", "pLastName", 30);
11. Employee e3 = new Employee(3, "kTestName", "sLastName", 31);
12. Employee e4 = new Employee(4, "dTestName", "zLastName", 25);
13.  
14. List</employee><employee> employees = new ArrayList</employee><employee>();
15. employees.add(e2);
16. employees.add(e3);
17. employees.add(e1);
18. employees.add(e4);
19.  
20. // UnSorted List
21. System.out.println(employees);
22.  
23. Collections.sort(employees);
24. // Default Sorting by employee id
25. System.out.println(employees);
26.  
27. Collections.sort(employees, new FirstNameSorter());
28. // Sorted by firstName
29. System.out.println(employees);
30.  
31. Collections.sort(employees, new LastNameSorter());
32. // Sorted by lastName
33. System.out.println(employees);
34.  
35. Collections.sort(employees, new AgeSorter());
36. // Sorted by age
37. System.out.println(employees);
38. }
39. }
40.  
41. Output:
42.  
43. Employee : 2 - nTestName - pLastName - 30
44. , Employee : 3 - kTestName - sLastName - 31
45. , Employee : 1 - aTestName - dLastName - 34
46. , Employee : 4 - dTestName - zLastName - 25
47. ]
48. [Employee : 1 - aTestName - dLastName - 34
49. , Employee : 2 - nTestName - pLastName - 30
50. , Employee : 3 - kTestName - sLastName - 31
51. , Employee : 4 - dTestName - zLastName - 25
52. ]
53. [Employee : 1 - aTestName - dLastName - 34
54. , Employee : 4 - dTestName - zLastName - 25
55. , Employee : 3 - kTestName - sLastName - 31
56. , Employee : 2 - nTestName - pLastName - 30
57. ]
58. [Employee : 1 - aTestName - dLastName - 34
59. , Employee : 2 - nTestName - pLastName - 30
60. , Employee : 3 - kTestName - sLastName - 31
61. , Employee : 4 - dTestName - zLastName - 25
62. ]
63. [Employee : 4 - dTestName - zLastName - 25
64. , Employee : 2 - nTestName - pLastName - 30
65. , Employee : 3 - kTestName - sLastName - 31
66. , Employee : 1 - aTestName - dLastName - 34
67. ]

Above class’s output shows clearly, now we are able to sort the collection of employees on any field using appropriate comparator implementation.

Understanding uses in other core collection classes

Its important to understand the importance of both interfaces in code collection APIs which have implicit behavior or sorting the elements. Such APIs are for example SortedMap or SortedSet.

These collections store elements in sorted order. To determining the sorting, they also use compare() method. Always remember if you Employee class does not implement Comparable interface and you are not using Comparator also, then adding elements in Sorted collections will give you error:

1. Exception in thread "main" java.lang.ClassCastException: corejava.compare.Employee cannot be cast to java.lang.Comparable
2. at java.util.TreeMap.put(Unknown Source)
3. at java.util.TreeSet.add(Unknown Source)
4. at corejava.compare.SortedSetTest.main(SortedSetTest.java:17)

So,its necessary to use either of both interfaces to able to store instances in sorted collections.

If you are not using comparator implementation, then Employee class’s compare() method will be used for sorting:

01. package corejava.compare;
02.  
03. import java.util.SortedSet;
04. import java.util.TreeSet;
05.  
06. public class SortedSetTest {
07. public static void main(String[] args) {
08. SortedSet</employee><employee> set = new TreeSet</employee><employee>();
09.  
10. Employee e1 = new Employee(1, "aTestName", "dLastName", 34);
11. Employee e2 = new Employee(2, "nTestName", "pLastName", 30);
12. Employee e3 = new Employee(3, "kTestName", "sLastName", 31);
13. Employee e4 = new Employee(4, "dTestName", "zLastName", 25);
14.  
15. set.add(e2);
16. set.add(e3);
17. set.add(e1);
18. set.add(e4);
19.  
20. System.out.println(set);
21. }
22. }

If you want to add some other sorting behavior using comparator implementation, you can pass the comparator to constructor of sorted collection. e.g.

01. package corejava.compare;
02.  
03. import java.util.SortedSet;
04. import java.util.TreeSet;
05.  
06. public class SortedSetTest {
07. public static void main(String[] args) {
08. SortedSet</employee><employee> set = new TreeSet</employee><employee>(new FirstNameSorter());
09.  
10. Employee e1 = new Employee(1, "aTestName", "dLastName", 34);
11. Employee e2 = new Employee(2, "nTestName", "pLastName", 30);
12. Employee e3 = new Employee(3, "kTestName", "sLastName", 31);
13. Employee e4 = new Employee(4, "dTestName", "zLastName", 25);
14.  
15. set.add(e2);
16. set.add(e3);
17. set.add(e1);
18. set.add(e4);
19.  
20. System.out.println(set);
21. }
22. }

In above code, comparator will take precedence and will become default sort order. So easy it is, right??

Now a bit of caution

If you have overridden equals() method in your Employee class, always remember to honor its behavior. I mean, if two objects are equal using equals() method that compare method should return ’0′ when comparing two such equal methods. It is required not to be surprised by abnormal behavior and not able to add element in sorted collections.

Hope i was clear enough in showing their usage. If you still have left with some doubts, leave a comment. I will be happy to resolve.

 

Happy Learning !!

转自:http://howtodoinjava.com/2012/10/21/when-to-use-comparable-and-comparator-interfaces-in-java/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值