简易Java(14):Comparable
与 Comparator
Comparable
和Comparator
是Java核心API提供的两个接口(interface)。从它们的名字就可以看出,他们用于比较对象的大小。但是,确切来说,它们到底是什么呢?以及它们直接有什么不同之处呢?接下来的两个例子来回答这个问题。这个简单的例子就是比较两种HDTV的尺寸。当阅读完下面的代码,你就知道如何使用Comparable
和Comparator
。
1、Comparable
一个类实现Comparable
接口,是为了可以让其自身的对象和其他对象进行比较。类本身必须实现这个接口,为的是可以和它自己的实例进行比较。要求实现的方法是compareTo()
。下面的这个例子来展示它的用法:
01 | package com.diguage.books.simplejava.ar14.comparable; |
08 | * Date: 2014-11-03 17:53 |
10 | public class HDTV implements Comparable<HDTV> { |
14 | public HDTV( int size, String brand) { |
19 | public int getSize() { |
23 | public void setSize( int size) { |
27 | public String getBrand() { |
31 | public void setBrand(String brand) { |
36 | public int compareTo(HDTV tv) { |
37 | if ( this .getSize() > tv.getSize()) { |
39 | } else if ( this .getSize() < tv.getSize()) { |
49 | package com.diguage.books.simplejava.ar14.comparable; |
56 | * Date: 2014-11-03 17:55 |
59 | public static void main(String[] args) { |
60 | HDTV tv1 = new HDTV( 55 , "Samsung" ); |
61 | HDTV tv2 = new HDTV( 60 , "Sony" ); |
62 | if (tv1.compareTo(tv2) > 0 ) { |
63 | System.out.println(tv1.getBrand() + " is better." ); |
65 | System.out.println(tv2.getBrand() + " is better." ); |
运行该程序,输入如下:
2、Comparator
对于比较对象间的不同属性,Comparator
能更好的胜任。例如,两个人可以基于name
和age
进行比较等。(这些情况,Comparable
就不可以胜任了。)
必须实现compare()
方法。现在,让我们使用其他方式来比较这些TV的尺寸。Comparator
的常用方法是排序。Collections
和Arrays
类都提供了一个可以使用Comparator
的排序方法。例子如下:
01 | package com.diguage.books.simplejava.ar14.comparator; |
08 | * Date: 2014-11-03 18:36 |
14 | public HDTV( int size, String brand) { |
19 | public int getSize() { |
23 | public void setSize( int size) { |
27 | public String getBrand() { |
31 | public void setBrand(String brand) { |
37 | package com.diguage.books.simplejava.ar14.comparator; |
39 | import java.util.Comparator; |
46 | * Date: 2014-11-03 19:10 |
48 | public class SizeComparator implements Comparator<HDTV> { |
50 | public int compare(HDTV tv1, HDTV tv2) { |
51 | int tv1Size = tv1.getSize(); |
52 | int tv2Size = tv2.getSize(); |
53 | if (tv1Size > tv2Size) { |
55 | } else if (tv1Size < tv2Size) { |
64 | package com.diguage.books.simplejava.ar14.comparator; |
66 | import java.util.ArrayList; |
67 | import java.util.Collections; |
75 | * Date: 2014-11-03 18:34 |
78 | public static void main(String[] args) { |
79 | HDTV tv1 = new HDTV( 55 , "Samsung" ); |
80 | HDTV tv2 = new HDTV( 60 , "Sony" ); |
81 | HDTV tv3 = new HDTV( 42 , "Panasonic" ); |
82 | List<HDTV> tvs = new ArrayList<HDTV>(); |
86 | Collections.sort(tvs, new SizeComparator()); |
87 | for (HDTV hdtv : tvs) { |
88 | System.out.println(hdtv.getBrand()); |
运行改程序,输入如下:
我们经常会使用Collections.reverseOrder()
来获取一个倒序的Comparator
。例如:
01 | package com.diguage.books.simplejava.ar14; |
06 | * Collections.reverseOrder()和Comparator的搭配使用。 |
10 | * Date: 2014-11-08 23:19 |
12 | public class CollectionsTestMain { |
13 | public static void main(String[] args) { |
14 | List<Integer> list = new ArrayList<Integer>(); |
18 | System.out.println(list); |
20 | Collections.sort(list); |
21 | System.out.println(list); |
23 | Comparator<Integer> comparator = Collections.reverseOrder(); |
24 | Collections.sort(list, comparator); |
25 | System.out.println(list); |
运行该程序,输入如下:
3、如何选择呢?
简单来说,一个实现Comparable
接口的类具有可比性,意思就是说它的实例相互直接可以进行比较。
一个实现Comparator
接口的类就一个比较器(Comparator),相对于其他类。首先,它可以被传入排序方法,例如Collections.sort()
或Arrays.sort()
,可精确控制排序顺序;其次,它还可以被用于控制已有的某行数据结构的顺序,例如排序的set或排序的map。
例如,创建TreeSet
,我们可以在构造函数中传入一个Comparator
,或者将一个类添加可比性。
方式一:TreeSet
(Comparator
比较器)
01 | package com.diguage.books.simplejava.ar14.treesetcomparator; |
08 | * Date: 2014-11-03 19:40 |
13 | public Dog( int size) { |
18 | public String toString() { |
26 | package com.diguage.books.simplejava.ar14.treesetcomparator; |
28 | import java.util.Comparator; |
35 | * Date: 2014-11-09 08:33 |
37 | public class SizeComparator implements Comparator<Dog> { |
39 | public int compare(Dog d1, Dog d2) { |
40 | return d1.size - d2.size; |
45 | package com.diguage.books.simplejava.ar14.treesetcomparator; |
47 | import java.util.TreeSet; |
54 | * Date: 2014-11-09 08:35 |
56 | public class ImpComparableMain { |
57 | public static void main(String[] args) { |
58 | TreeSet<Dog> d = new TreeSet<Dog>( new SizeComparator()); |
62 | System.out.println(d); |
方式二:实现Comparable
01 | package com.diguage.books.simplejava.ar14.treesetcomparable; |
08 | * Date: 2014-11-09 08:41 |
10 | public class Dog implements Comparable<Dog> { |
13 | public Dog( int size) { |
18 | public int compareTo(Dog o) { |
19 | return o.size - this .size; |
23 | public String toString() { |
31 | package com.diguage.books.simplejava.ar14.treesetcomparable; |
33 | import java.util.TreeSet; |
40 | * Date: 2014-11-09 08:43 |
42 | public class ImpComparableMain { |
43 | public static void main(String[] args) { |
44 | TreeSet<Dog> d = new TreeSet<Dog>(); |
49 | System.out.println(d); |
《Simple Java》是一本讲解Java面试题的书。讲解也有不少独特之处,为了面试,《简易Java》走起!