简易Java(14):Comparable
与 Comparator
Comparable
和Comparator
是Java核心API提供的两个接口(interface)。从它们的名字就可以看出,他们用于比较对象的大小。但是,确切来说,它们到底是什么呢?以及它们直接有什么不同之处呢?接下来的两个例子来回答这个问题。这个简单的例子就是比较两种HDTV的尺寸。当阅读完下面的代码,你就知道如何使用Comparable
和Comparator
。
1、Comparable
一个类实现Comparable
接口,是为了可以让其自身的对象和其他对象进行比较。类本身必须实现这个接口,为的是可以和它自己的实例进行比较。要求实现的方法是compareTo()
。下面的这个例子来展示它的用法:
package com.diguage.books.simplejava.ar14.comparable; /** * Comparable接口使用示例 * <p/> * Coder:D瓜哥,http://www.diguage.com/ * <p/> * Date: 2014-11-03 17:53 */ public class HDTV implements Comparable<HDTV> { private int size; private String brand; public HDTV(int size, String brand) { this.size = size; this.brand = brand; } public int getSize() { return size; } public void setSize(int size) { this.size = size; } public String getBrand() { return brand; } public void setBrand(String brand) { this.brand = brand; } @Override public int compareTo(HDTV tv) { if (this.getSize() > tv.getSize()) { return 1; } else if (this.getSize() < tv.getSize()) { return -1; } else { return 0; } } } package com.diguage.books.simplejava.ar14.comparable; /** * 运行入口 * <p/> * Coder:D瓜哥,http://www.diguage.com/ * <p/> * Date: 2014-11-03 17:55 */ public class Main { public static void main(String[] args) { HDTV tv1 = new HDTV(55, "Samsung"); HDTV tv2 = new HDTV(60, "Sony"); if (tv1.compareTo(tv2) > 0) { System.out.println(tv1.getBrand() + " is better."); } else { System.out.println(tv2.getBrand() + " is better."); } } }
运行该程序,输入如下:
Sony is better.
2、Comparator
对于比较对象间的不同属性,Comparator
能更好的胜任。例如,两个人可以基于name
和age
进行比较等。(这些情况,Comparable
就不可以胜任了。)
必须实现compare()
方法。现在,让我们使用其他方式来比较这些TV的尺寸。Comparator
的常用方法是排序。Collections
和Arrays
类都提供了一个可以使用Comparator
的排序方法。例子如下:
package com.diguage.books.simplejava.ar14.comparator; /** * Model类 * <p/> * Coder:D瓜哥,http://www.diguage.com/ * <p/> * Date: 2014-11-03 18:36 */ public class HDTV { private int size; private String brand; public HDTV(int size, String brand) { this.size = size; this.brand = brand; } public int getSize() { return size; } public void setSize(int size) { this.size = size; } public String getBrand() { return brand; } public void setBrand(String brand) { this.brand = brand; } } package com.diguage.books.simplejava.ar14.comparator; import java.util.Comparator; /** * Comparator使用示例 * <p/> * Coder:D瓜哥,http://www.diguage.com/ * <p/> * Date: 2014-11-03 19:10 */ public class SizeComparator implements Comparator<HDTV> { @Override public int compare(HDTV tv1, HDTV tv2) { int tv1Size = tv1.getSize(); int tv2Size = tv2.getSize(); if (tv1Size > tv2Size) { return 1; } else if (tv1Size < tv2Size) { return -1; } else { return 0; } } } package com.diguage.books.simplejava.ar14.comparator; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * Comparator示例主类 * <p/> * Coder:D瓜哥,http://www.diguage.com/ * <p/> * Date: 2014-11-03 18:34 */ public class Main { public static void main(String[] args) { HDTV tv1 = new HDTV(55, "Samsung"); HDTV tv2 = new HDTV(60, "Sony"); HDTV tv3 = new HDTV(42, "Panasonic"); List<HDTV> tvs = new ArrayList<HDTV>(); tvs.add(tv1); tvs.add(tv2); tvs.add(tv3); Collections.sort(tvs, new SizeComparator()); for (HDTV hdtv : tvs) { System.out.println(hdtv.getBrand()); } } }
运行改程序,输入如下:
Panasonic Samsung Sony
我们经常会使用Collections.reverseOrder()
来获取一个倒序的Comparator
。例如:
package com.diguage.books.simplejava.ar14; import java.util.*; /** * Collections.reverseOrder()和Comparator的搭配使用。 * <p/> * Coder:D瓜哥,http://www.diguage.com/ * <p/> * Date: 2014-11-08 23:19 */ public class CollectionsTestMain { public static void main(String[] args) { List<Integer> list = new ArrayList<Integer>(); list.add(3); list.add(1); list.add(2); System.out.println(list); Collections.sort(list); System.out.println(list); Comparator<Integer> comparator = Collections.reverseOrder(); Collections.sort(list, comparator); System.out.println(list); } }
运行该程序,输入如下:
[3, 1, 2] [1, 2, 3] [3, 2, 1]
3、如何选择呢?
简单来说,一个实现Comparable
接口的类具有可比性,意思就是说它的实例相互直接可以进行比较。
一个实现Comparator
接口的类就一个比较器(Comparator),相对于其他类。首先,它可以被传入排序方法,例如Collections.sort()
或Arrays.sort()
,可精确控制排序顺序;其次,它还可以被用于控制已有的某行数据结构的顺序,例如排序的set或排序的map。
例如,创建TreeSet
,我们可以在构造函数中传入一个Comparator
,或者将一个类添加可比性。
方式一:TreeSet
(Comparator
比较器)
package com.diguage.books.simplejava.ar14.treesetcomparator; /** * Dog * <p/> * Coder:D瓜哥,http://www.diguage.com/ * <p/> * Date: 2014-11-03 19:40 */ public class Dog { int size; public Dog(int size) { this.size = size; } @Override public String toString() { return "Dog{" + "size=" + size + '}'; } } package com.diguage.books.simplejava.ar14.treesetcomparator; import java.util.Comparator; /** * Dog的比较器 * <p/> * Coder:D瓜哥,http://www.diguage.com/ * <p/> * Date: 2014-11-09 08:33 */ public class SizeComparator implements Comparator<Dog> { @Override public int compare(Dog d1, Dog d2) { return d1.size - d2.size; } } package com.diguage.books.simplejava.ar14.treesetcomparator; import java.util.TreeSet; /** * Comparator示例主类 * <p/> * Coder:D瓜哥,http://www.diguage.com/ * <p/> * Date: 2014-11-09 08:35 */ public class ImpComparableMain { public static void main(String[] args) { TreeSet<Dog> d = new TreeSet<Dog>(new SizeComparator()); // 传入比较器 d.add(new Dog(2)); d.add(new Dog(1)); d.add(new Dog(3)); System.out.println(d); } }
方式二:实现Comparable
package com.diguage.books.simplejava.ar14.treesetcomparable; /** * Dog类 * <p/> * Coder:D瓜哥,http://www.diguage.com/ * <p/> * Date: 2014-11-09 08:41 */ public class Dog implements Comparable<Dog> { int size; public Dog(int size) { this.size = size; } @Override public int compareTo(Dog o) { return o.size - this.size; } @Override public String toString() { return "Dog{" + "size=" + size + '}'; } } package com.diguage.books.simplejava.ar14.treesetcomparable; import java.util.TreeSet; /** * Comparable示例主类 * <p/> * Coder:D瓜哥,http://www.diguage.com/ * <p/> * Date: 2014-11-09 08:43 */ public class ImpComparableMain { public static void main(String[] args) { TreeSet<Dog> d = new TreeSet<Dog>(); d.add(new Dog(1)); d.add(new Dog(2)); d.add(new Dog(3)); System.out.println(d); } }
《Simple Java》是一本讲解Java面试题的书。讲解也有不少独特之处,为了面试,《简易Java》走起!
原文链接:Comparable 与
Comparator
">https://wordpress.diguage.com/archives/120.html版权声明:非特殊声明均为本站原创作品,转载时请注明作者和原文链接。