Java 8:实施可比较

Java 8: implementing Comparable

我喜欢 Comparator 的新静态工厂方法,因为它们允许以非常简洁且不易出错的方式实现比较器。

但是推荐的实施方式是什么Comparable?我们应该在 Comparable 实现中使用 Comparators 吗?

public MyClass implements Comparable<MyClass>{
...
    public int compareTo(MyClass other){
        Comparator<MyClass> naturalOrderComparator = 
            Comparator.comparing(MyClass::getFoo)
                      .thenComparing(MyClass::getBar);
        return naturalOrderComparator.compare(this, other);
    } 
}

甚至在对大型集合进行排序时使用静态比较器来减少大量对象创建:

public MyClass implements Comparable<MyClass>{
    private static final Comparator<MyClass> NATURAL_ORDER_COMPARATOR =     
        Comparator.comparing(MyClass::getFoo)
                  .thenComparing(MyClass::getBar);

    ...

    public int compareTo(MyClass other){
        return NATURAL_ORDER_COMPARATOR.compare(this, other);
    } 
}

或者是否有另一种推荐的方法来实现 Comparable with Java SE 8?

您自己的选项 2 几乎可以肯定是目前可用的最佳方式。它避免了分配,读起来很好——尤其是当你把静态常量放在 compareTo 方法旁边时。

Java8 中的新 Comparator.comparing 工厂方法非常容易阅读,更好的是,很难搞砸 -- 有很多很多方法可以手写错误的比较,比我想记住的要多,而且工厂方法对其中的大多数都是免疫的。尽管使用它们来编写 compareTo 方法而不是 Comparator 对象有点奇怪,但它仍然比替代方法更好。

Java-8 之前的一般最佳做法是使用 Guava's ComparisonChain and Ordering 实用程序。它们抽象出正确实现 .compareTo()/.compare() 方法的繁琐且容易出错的细节,并允许您编写一个人类可读的步骤序列来定义对象应该如何比较. Ordering 实现了 Comparator,但是定义 Ordering 并在 Comparable.compareTo() 方法中调用它没有任何问题。

请注意,由于 Java 8 中 JDK 的添加,Ordering 被描述为已过时:

If you are using Java 8, this class is now obsolete.... Most of its functionality is now provided by Stream and by Comparator itself, and the rest can now be found as static methods in our new Comparators class.