03
11 月

Java Comparable 和 Comparator 的对比

Java Comparable 和 Comparator 的对比

Comparable 和 Comparator 均为Java Core API 接口,由名字可以判断出它们是由来比较东西的,但具体功能和区别又如何呢?本文将通过两个例子来回答这个问题,例子中对比了高清电视(HDTV)的尺寸。看过例子后,该如何使用Comparable 和 Comparator就很简单了。

1. Comparable

一个类实现了Comparable接口后,该类的实例之间能进行比较。实现Comparable接口必须实现compareTo()方法,如下例所示:

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;
	}
}
 
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.");
		}
	}
}
/* Output:
Sony is better.
*///:~

2. Comparator

某些情况下,你可能不想修改类但又需要让其有可比性,此时可以使用Comparator,它基于某个属性值或域来进行目标对象的对比。例如,两个人之间可以通过年龄或身高来进行对比(此时无法使用Comparable)。 这个接口需要类实现compare()方法,现在我们有另外一种方式有尺寸来比较电视。Comparator的一种通常用法是排序,CollectionsArrays都提供了使用Comparator来排序的方法。

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
 
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;
	}
}
 
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;
		}
	}
}
 
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");
 
		ArrayList<HDTV> al = new ArrayList<HDTV>();
		al.add(tv1);
		al.add(tv2);
		al.add(tv3);
 
		Collections.sort(al, new SizeComparator());
		for (HDTV a : al) {
			System.out.println(a.getBrand());
		}
	}
}/* Output:
Panasonic
Samsung
Sony
*///:~

也经常使用Collections.reverseOrder()方法来反转,得到降序结果:

ArrayList<Integer> al = new ArrayList<Integer>();
al.add(3);
al.add(1);
al.add(2);
System.out.println(al);
Collections.sort(al);
System.out.println(al);
 
Comparator<Integer> comparator = Collections.reverseOrder();
Collections.sort(al,comparator);
System.out.println(al);

输出为:

[3,1,2]
[1,2,3]
[3,2,1]

3. 该使用Comparable还是Comparator

实现了Comparable的类具有可比性,其实例能够直接比较。

实现了Comparator的类主要使用在以下两种情形:

  • 能够传递给排序方法,如Collections.sort()Arrays.sort(),能够实现指定的排序。
  • 能够控制确切的数据结构,如TreeSetTreeMap

例如,创建一个TreeSet时,可以传递给构造器一个Comparator,或者直接让类具有可比性。

应用 1 – TreeSet(Comparator comparator)

class Dog {
	int size;
 
	Dog(int s) {
		size = s;
	}
}
 
class SizeComparator implements Comparator<Dog> {
	@Override
	public int compare(Dog d1, Dog d2) {
		return d1.size - d2.size;
	}
}
 
public class ImpComparable {
	public static void main(String[] args) {
		TreeSet<Dog> d = new TreeSet<Dog>(new SizeComparator()); // pass comparator
		d.add(new Dog(1));
		d.add(new Dog(2));
		d.add(new Dog(1));
	}
}

应用 2 – 实现Comparable接口

class Dog implements Comparable<Dog>{
	int size;
 
	Dog(int s) {
		size = s;
	}
 
	@Override
	public int compareTo(Dog o) {
		return o.size - this.size;
	}
}
 
public class ImpComparable {
	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(1));
	}
}

没有评论