我什么时候应该实施比较器?

时间:2017-05-20 20:51:31

标签: java comparator treemap comparable sortedmap

所以我正在学习Comparator和Comparable,我遇到了以下问题。 我有一节课:

extension=protobuf.so

另一个类,Name实现Comparable,并且在构造函数中首先有两个字符串。我不完全理解的是Comparator的功能,我已经阅读了Java文档,我知道它用于对元素进行不同的排序而不更改我的示例中的Name类,它在某些情况下也可以允许空值,但是这个声明在我的类构造函数中工作正常,我根本不需要在PhoneBook类中实现Comparator接口:

public class PhoneBook implements Comparator<Name>{

    private SortedMap<Name, Integer> directory ;

    //class code constructor etc.

    //this is the method that the compiler wants if implementing Comparator
    @Override
    public int compare(Name o1, Name o2) {

        return o1.firstName.compareTo(o2.firstName);
      }
}

实现了我希望它实现的功能,而无需通过PhoneBook类实现Comparator接口。我的问题是类何时可能要实现Comparator接口?是否有不同的方法让地图使用不同的排序方法(比类名中的Comparable接口提供的排序方法),而不是在初始化时传递匿名类?如果这个问题不够清楚,或者不适合这个网站,我很抱歉。

编辑:我理解Comparable vs Comparator的论点以及何时使用它们。我的问题更多是关于如何使用Comparator。初始化时,你可以在不通过新的比较器的情况下对地图进行排序吗?类是什么时候实现这个接口的好主意?

1 个答案:

答案 0 :(得分:1)

实现Comparator的类不应该执行任何其他操作。

由于大多数此类仅在一个地方使用,因此将它们实现为未命名非常常见,即与第二个示例中的匿名类一样。

但是,如果您希望Comparator可以重复使用,那么为它创建一个独立的类是个好主意,例如:在你的例子中命名为FirstNameComparator

请注意,在Java 8+中,使用lambda表达式而不是匿名类(因为这在逻辑上是lambda表达式变成了什么)以及可重用比较的方法引用会更容易。

// Using anonymous class (Java 1.2+)
this.directory = new TreeMap<Name, Integer>(new Comparator<Name>() {
    @Override
    public int compare(Name n1, Name n2) {
        return n1.getFirstName().compareTo(n2.getFirstName());
    }
});
// Reusable named class (Java 1.2+)
public final class FirstNameComparator implements Comparator<Name> {
    @Override
    public int compare(Name n1, Name n2) {
        return n1.getFirstName().compareTo(n2.getFirstName());
    }
}

// Then use it like this:
this.directory = new TreeMap<Name, Integer>(new FirstNameComparator());
// Using lambda expression (Java 8+)
this.directory = new TreeMap<Name, Integer>(
    (n1, n2) -> n1.getFirstName().compareTo(n2.getFirstName())
);
// Using method reference (Java 8+)
public class PhoneBook {
    public PhoneBook(ArrayList<Name> names, ArrayList<Integer> phones) {
        this.directory = new TreeMap<Name, Integer>(PhoneBook::compareFirstName);
        // other constructor code
    }
    private static int compareFirstName(Name n1, Name n2) { // public, if reusable
        return n1.getFirstName().compareTo(n2.getFirstName());
    }
    // other PhoneBook code
}
// Using Comparator helper (Java 8+)
this.directory = new TreeMap<Name, Integer>(Comparator.comparing(Name::getFirstName));