Java Comparator和Comparabler的区别

接触java没多久,前几天用到排序的问题,看到Comparator和Comparable两个接口类有点迷惑,研究了两天也没理解有什么区别,今天在看《Java核心编程》时,才恍然大悟。在这里表达一下自己的想法。

  当需要排序的集合或数组时可以使用Comparator或Comparable,它们都可以实现排序,但是它们的区别是Comparator从外部定义了对象的比较规则,而Comparable则是从内部定义了对象是可比较的。下面将详细解这句话。

Comparator

  Comparator从外部定义了对象的比较规则

  比如,你要使用某人写的一个矩形类Rect。现在你有一个Rect的集合(或数组),你想实现对Rect的排序,现在有一个问题,某人在实现Rect的时候没有考虑到会有人将会比较Rect对象。这个时候你必须根据需要对Rect进行排序(比如,根据矩形的长进行排序),在这个场景下使用Comparator,因为Rect类已经存在,你不能对其进行改变。


 1 import java.util.*;
 2 
 3 public class Rectangle {
 4     
 5     public static void main(String[] args)
 6     {
 7         Rect[] rectArrays = new Rect[] {new Rect(3, 4), new Rect(5, 2), new Rect(4, 5)};
 8         
 9         // 排序,将定义的RectComparator作为参数
10         Arrays.sort(rectArrays, new RectComparator());
11         
12         for (int i=0; i != rectArrays.length; ++i)
13             System.out.println(rectArrays[i]);
14     }
15     
16     // 定义一个Rect比较方式:根据Rect的长比较
17     public static class RectComparator implements Comparator<Rect>
18     {
19         public int compare(Rect o1, Rect o2)
20         {
21             return o1.getLength() - o2.getLength();
22         }
23     }
24 
25     public static class Rect
26     {
27         Rect(int l, int w)
28         {
29             this.length = l;
30             this.width = w;
31         }
32         
33         public int getLength()
34         {
35             return this.length;
36         }
37         
38         public int getWidth()
39         {
40             return this.width;
41         }
42         
43         public int getArea()
44         {
45             return this.length * this.width;
46         }
47         
48         public String toString()
49         {
50             return "length: " + length + "  " + width;
51         }
52         
53         private int length;
54         private int width;
55     }
56 }


输出:

length: 3 4
length: 4 5
length: 5 2

Comparable

  Comparable则是从内部定义了对象的是可比较的

  还是以Rect为例,假如你是Rect的实现者,在你定义Rect时,你觉得有必要定义一个比较方式,这个时候就应该使Rect继承Comparable接口。如果你觉得较合理的排序方式是根据Rect的面积进行排序,那么可以这样实现

 1 import java.util.*;
 2 
 3 public class Rectangle {
 4     
 5     public static void main(String[] args)
 6     {
 7         Rect[] rectArrays = new Rect[] {new Rect(3, 4), new Rect(5, 2), new Rect(4, 5)};
 8         
 9         Arrays.sort(rectArrays);
10         
11         for (int i=0; i != rectArrays.length; ++i)
12             System.out.println(rectArrays[i]);
13     }
14 
15     // 定义了Comparable接口
16     public static class Rect implements Comparable<Rect>
17     {
18         Rect(int l, int w)
19         {
20             this.length = l;
21             this.width = w;
22         }
23         
24         public int getLength()
25         {
26             return this.length;
27         }
28         
29         public int getWidth()
30         {
31             return this.width;
32         }
33         
34         public int getArea()
35         {
36             return this.length * this.width;
37         }
38         
39         public String toString()
40         {
41             return "length: " + length + "  " + width;
42         }
43         
44         // 重载compareTo函数,按面积比较
45         @Override
46         public int compareTo(Rect that)
47         {
48             return this.getArea() - that.getArea();
49         }
50         
51         private int length;
52         private int width;
53     }
54 }

输出:

length: 5 2
length: 3 4
length: 4 5

总结

通过Comparator和Comparable的意思我们也可以看出两者的区别
Comparable意为“可比较的”,一个类继承了Camparable接口则表明这个类的对象之间是可以相互比较的,这个类对象组成的集合就可以直接使用sort方法排序。
Comparator意为“比较算子”,因此Comparator可以看成一种算法的实现,将算法和数据分离。

  另外,通过定义方式,我们可以发现如果一个类继承了Comparable接口,则表明这个类的对象之间是可以比较的,且比较的方式只有一种。但是Comparator可以定义多种比较方式。在第二个程序中,Rect定义了按面积进行比较,如果我们想按长对Rect进行排序,那么也可以通过Comparator来实现。

  最后,再次强调Comparator从外部定义了对象的比较规则,而Comparable则是从内部定义了对象是可比较的

参考资料

 
原文地址:https://www.cnblogs.com/yuxiaoqi/p/3266172.html