65.9K
CodeProject 正在变化。 阅读更多。
Home

Comparator 和 Comparable 对象

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.86/5 (5投票s)

2013年12月28日

CPOL

3分钟阅读

viewsIcon

27670

downloadIcon

155

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 类。我为这个类提供了一个包含以下字段的构造函数:idnameageheight。我使用了 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日:初始帖子
© . All rights reserved.