Comparator 和 Comparable 对象






4.86/5 (5投票s)
Comparator 和 Comparable 对象教程
引言
初学者对 Comparator 和 Comparable 常常感到困惑。主要原因是缺乏对它们是什么以及它们之间区别的理解。
背景
CompareTo – 方法用于比较当前启动该方法的元素与其他传递到该方法的对象。如果当前元素大于传递的元素,则该方法返回一个正数,如果小于,则返回一个负数,如果相等,则返回 0。
自然排序 – 最适合用于在当前类中进行比较的参数。例如,Employee
经常通过他们的 "Performances
" 来比较。
理解定义
可比较
可以通过它们的 *自然排序* 与其他对象进行比较的对象。
实现 Comparable
意味着 "我可以与另一个对象进行比较。" 当只有一个自然的默认比较时,这通常很有用。 © Jon Skeet。
示例:如果我有一个 IdCard
类,那么此场景的 *自然排序* 是通过 Id
号码。
Comparator
独立的特定类,旨在通过特定字段比较两个对象。
Comparators 允许我们添加更多比较对象的方式。
实现 Comparator 意味着 "我可以比较另外两个对象。" 当有多种比较同一类型的两个实例的方式时,这通常很有用。 © Jon Skeet。
示例:我们可以通过 年龄
、身高
等属性来比较 2 个人。
可比较
Person.java
public class Person implements Comparable<Object> {
public int id;
public String name;
public int age;
public int height;
public Person(int id, String name, int age, int height) {
this.id = id;
this.name = name;
this.age = age;
this.height = height;
}
@Override
public int compareTo(Object o) {
return this.id - ((Person)o).id;
}
@Override
public String toString() {
return String.format("[Name: %s/Age: %d/Height: %d]", name, age, height);
}
}
为了说明 Comparable
接口,我选择创建一个简单的 Person
类。我为这个类提供了一个包含以下字段的构造函数:id
、name
、age
和 height
。我使用了 Comparable<Object>
接口并实现了它的 compareTo
方法。因为在我的程序中,Person
对象是通过 id
进行比较的,所以我实现了 compareTo
方法,使其受制于对象的 id
成员。这可以很容易地更改以适应您自己的 Class
。现在我们可以将 person
对象与其他 person
对象进行比较,比较将如下所示
// Comparable
System.out.println("Is Bar id bigger than Sam ? " + pBar.compareTo(pSam));
输出
System.out.println("Is Bar id bigger than Sam ? " + pBar.compareTo(pSam));
另一个例子:一个男人的钱包
我们知道钱包通常会通过它包含的金额来比较。所以一个合适的 Wallet
类将是这样的
public class Wallet implements Comparable<Object> {
public int money = 0;
public String name;
public Wallet(String name, int money) {
this.name = name;
this.money = money;
}
@Override
public int compareTo(Object o) {
return this.money - ((Wallet)o).money;
}
}
Comparators
Comparators 是实现 "Comparator
" 接口的独立类。
Comparators 的主要用途是排序,每个 comparator 将在 compareTo
中实现自己的排序逻辑。 之后,comparator 将通过一个排序算法传递,该算法将使用传递的 comparator 排序逻辑。
例如:HeightComparator
将比较两个对象的 height
字段。
HeightComparator.java
import java.util.Comparator;
public class HeightComparator implements Comparator<Object> {
@Override
public int compare(Object o1, Object o2) {
int p1 = ((Person)o1).height;
int p2 = ((Person)o2).height;
return p1 - p2;
}
}
此 comparator 将两个接收到的对象转换为 Person
对象,并且当第一个对象大于第二个对象时返回一个正数,否则当第二个对象大于第一个对象时返回负数,否则它返回零,因为它们两个相等。
Comparator 还有另一个用途。 我们可以使用它,而无需对整个集合进行排序,通过创建目标 comparator,然后将我们要比较的对象传递给它。
探索示例
MainClass.java
// Declaring Person objects.
ArrayList<Person> peoples = new ArrayList<Person>();
Person pOrel = new Person(1, "Orel", 27, 186);
Person pBar = new Person(2, "Bar", 28, 165);
Person pSam = new Person(3, "Sam", 25, 170);
peoples.add(pOrel);
peoples.add(pBar);
peoples.add(pSam);
我创建了一个 Person
ArrayList
来保存我们的集合。我创建了 3 个 Person
实例并将它们添加到我们的集合中。
// Comparable
System.out.println("Is Bar id bigger than Sam ? " + pBar.compareTo(pSam));
我通过比较 pBar
是否大于 pSam
来测试 Person
比较方法,众所周知,这将使用 Person
compareTo
方法来查看 pBar
的 id 号是否大于 pSam
的 id 号(false, pSam
的 id 大于)。
输出
Is Bar id bigger than Sam ? -1
// Comparators 2nd usage.
System.out.println("Does Orel taller than Sam ? " +
new HeightComparator().compare(pOrel, pSam));
我使用了特定的 comparator 以发现 pOrel
是否比 pSam
高。
输出
Does Orel taller than Sam ? 16
// Comparators 1st usage.
// Passing Collections sort methods our collection and the
// specified Comparator we want to use in order to sort the collection.
Collections.sort(peoples, new AgeComparator());
System.out.println("Compare by Age");
MyLibrary.printObjects(peoples);
我正在传递我们的排序算法 peoples
集合和 AgeComparator
,以便根据 AgeComparator
中的 compare
方法中的逻辑对我们的集合进行排序。 然后使用一个普通的 static
方法来打印结果。
输出
Compare by Age
[Name: Sam/Age: 25/Height: 170] [Name: Orel/Age: 27/Height: 186]
[Name: Bar/Age: 28/Height: 165]
结论
使用 Comparable 和 Comparators 可以很容易地简化您的代码,当需要进行排序任务时。这将使您的代码更通用、更具可读性和更清晰。
历史
- 2013年12月28日:初始帖子