java.lang.Comparable Comparator

Comparable自然排序

public interface Comparable<T>此接口强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的 compareTo 方法被称为它的自然比较方法。

我们应该如何对事物进行比较和排序?这问题听上去有点莫名其妙,但我希望你认真考虑一下。比方说,我们有一组苹果:

例1

我们要怎样对它们进行排序呢?我们希望通过重量进行排序吗?如果是的话,排序是从最轻到最重还是从最重到最轻?当我们对它们进行排序的时候,我们需要反复比较两个苹果的重量,直到正确地排好所有的苹果。苹果1比苹果2重?那它比苹果3重吗?我们需要不断比较,直到完成排序。Comparable接口可以帮助我们实现这一目标。Comparable本身不能对对象进行排序,但接口定义的方法 int compareTo(T)可以。

compareTo(T)如何工作

让我们通过使用compareTo()方法来看看哪个苹果更重,开始吧。

例2

compareTo()方法的工作原理是返回一个int值——或正,或负,或为零。它通过调用作为参数的对象来比较对象。负数表示调用的对象比参数“轻”。如果我们用大小来比较苹果,那么上面的调用会返回一个负数,例如-400,因为红苹果比青苹果小。如果两个苹果重量相等,那么调用将返回0。如果红苹果更重,那么compareTo()将返回一个正数,例如68。

compareTo()的灵活性

如果我们反复调用上面的compareTo()方法,那么我们可以通过大小来排序,这很棒,但并非故事的结束。如果我们想通过颜色来给苹果排序呢?抑或是重量?

他可以通过回答这两个问题来做到这一点:

  1. 他希望苹果如何进行排序?他希望我们比较什么特征?
  2. 在那样的环境中,“小于”,“等于”和“大于”指的是什么意思?

例1:通过重量排序苹果

在第一个例子中,我们将通过重量对苹果排序。只需要一行代码。

Collections.sort(apples);

上面的代码行可以为我们做到所有的排序工作,只要我们事先定义好如何对苹果进行排序。

让我们开始写苹果类吧。

public class Apple implements Comparable {
    private String variety;
    private Color color;
    private int weight;
    @Override
    public int compareTo(Apple other) {
        if (this.weight < other.weight) {
            return -1;
        }
        if (this.weight == other.weight) {
            return 0;
        }
        return 1;
    }
}

例2:通过多个特征排序苹果

@Override
public int compareTo(Apple other) {
     int result = this.variety.compareTo(other.variety);
     if (result == 0) {
          result = this.color.compareTo(other.color);
     }
     if (result == 0) {
          result = Integer.compare(this.weight, other.weight);
     }
     return result;
}

Comparable,hashCode以及Equals

你可能会注意到compareTo()看起来有点像hashCode()和equals()方法。但是,它们有一个重要的区别。对于hashCode()和equals()方法,比较个体属性的顺序不影响返回的值,但是,在compareTo()中,通过你比较对象的顺序来定义对象的顺序。

结论

在结论中我只想强调Comparable接口是多么的重要。它既用于java.util.Arrays,也用于java.util.Collections实用程序类,来排序元素和搜索排序集合中的元素。使用TreeSet和Tree Map,就更简单了——想要它们会自动排序必须实现Comparable接口的元素。

Comparator 定制排序

Comparator 在 java.util 包下,也是一个接口,JDK 1.8 以前只有两个方法:

public interface Comparator<T> {

    public int compare(T lhs, T rhs);

    public boolean equals(Object object);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

JDK 1.8 以后又新增了很多方法:

shixinzhang

 Comparator 是在外部制定排序规则,然后作为排序策略参数传递给某些类,比如 Collections.sort(), Arrays.sort(), 或者一些内部有序的集合(比如 SortedSet,SortedMap 等)。

举个例子:

        // 1.创建一个实现 Comparator 接口的对象
        Comparator comparator = new Comparator() {
            @Override
            public int compare(Object object1, Object object2) {
                if (object1 instanceof NewBookBean && object2 instanceof NewBookBean){
                    NewBookBean newBookBean = (NewBookBean) object1;
                    NewBookBean newBookBean1 = (NewBookBean) object2;
                    //具体比较方法参照 自然排序的 compareTo 方法,这里只举个栗子
                    return newBookBean.getCount() - newBookBean1.getCount();
                }
                return 0;
            }
        };

        //2.将此对象作为形参传递给 TreeSet 的构造器中
        TreeSet treeSet = new TreeSet(comparator);

        //3.向 TreeSet 中添加 步骤 1 中 compare 方法中设计的类的对象
        treeSet.add( new NewBookBean("A",34));
        treeSet.add( new NewBookBean("S",1));
        treeSet.add( new NewBookBean("V",46));
        treeSet.add( new NewBookBean("Q",26));
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

其实可以看到,Comparator 的使用是一种策略模式,不熟悉策略模式的同学可以点这里查看: 策略模式:网络小说的固定套路 了解。

排序类中持有一个 Comparator 接口的引用:

Comparator<? super K> comparator;
  • 1
  • 2

而我们可以传入各种自定义排序规则的 Comparator 实现类,对同样的类制定不同的排序策略。


总结

Java 中的两种排序方式:

  1. Comparable 自然排序。(实体类实现)
  2. Comparator 是定制排序。(无法修改实体类时,直接在调用方创建)

同时存在时采用 Comparator(定制排序)的规则进行比较。

对于一些普通的数据类型(比如 String, Integer, Double…),它们默认实现了Comparable 接口,实现了 compareTo 方法,我们可以直接使用。

而对于一些自定义类,它们可能在不同情况下需要实现不同的比较策略,我们可以新创建 Comparator 接口,然后使用特定的 Comparator 实现进行比较。

这就是 Comparable 和 Comparator 的区别。


http://www.codeceo.com/article/java-comparable-5-minutes.html。https://blog.csdn.net/u011240877/article/details/53399019

猜你喜欢

转载自blog.csdn.net/ssyyjj88/article/details/80277385