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: " + width; 51 } 52 53 private int length; 54 private int width; 55 } 56 }
输出:
length: 3 width: 4
length: 4 width: 5
length: 5 width: 2
length: 4 width: 5
length: 5 width: 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: " + 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 width: 2
length: 3 width: 4
length: 4 width: 5
length: 3 width: 4
length: 4 width: 5
总结
通过Comparator和Comparable的意思我们也可以看出两者的区别
Comparable意为“可比较的”,一个类继承了Camparable接口则表明这个类的对象之间是可以相互比较的,这个类对象组成的集合就可以直接使用sort方法排序。
Comparator意为“比较算子”,因此Comparator可以看成一种算法的实现,将算法和数据分离。
另外,通过定义方式,我们可以发现如果一个类继承了Comparable接口,则表明这个类的对象之间是可以比较的,且比较的方式只有一种。但是Comparator可以定义多种比较方式。在第二个程序中,Rect定义了按面积进行比较,如果我们想按长对Rect进行排序,那么也可以通过Comparator来实现。
最后,再次强调Comparator从外部定义了对象的比较规则,而Comparable则是从内部定义了对象是可比较的。
Comparable意为“可比较的”,一个类继承了Camparable接口则表明这个类的对象之间是可以相互比较的,这个类对象组成的集合就可以直接使用sort方法排序。
Comparator意为“比较算子”,因此Comparator可以看成一种算法的实现,将算法和数据分离。
另外,通过定义方式,我们可以发现如果一个类继承了Comparable接口,则表明这个类的对象之间是可以比较的,且比较的方式只有一种。但是Comparator可以定义多种比较方式。在第二个程序中,Rect定义了按面积进行比较,如果我们想按长对Rect进行排序,那么也可以通过Comparator来实现。
最后,再次强调Comparator从外部定义了对象的比较规则,而Comparable则是从内部定义了对象是可比较的。
参考资料
- 《Java核心编程》第7版,p91-p92
- Comparator和Comparable在排序中的应用
- Java Comparator和Comparabler的区别