我什么时候应该实施比较器?
When should I implement Comparator?
所以我正在学习 Comparator 和 Comparable,我遇到了以下问题。
我有一个 class:
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);
}
}
另一个class,Name实现了Comparable,构造函数中有first和last两个String。我不完全理解的是 Comparator 的功能,我已经阅读了 Java 文档并且我知道它用于对元素进行不同的排序而不更改名称 class 在我的示例中它也可以允许 null某些情况下的值,但我的 class 构造函数中的这个声明工作正常,我根本不需要在 PhoneBook class 中实现比较器接口:
Public PhoneBook(ArrayList<Name> names, ArrayList<Integer> phones) {
this.directory = new TreeMap<Name, Integer>(new Comparator<Name>(){
@Override
public int compare(Name o1, Name o2) {
return o1.firstName.compareTo(o2.firstName);
}
});
//other constructor code to populate map
}
并且实现了我希望它实现的功能,而不需要PhoneBook实现Comparator接口class。我的问题是 class 什么时候想要实现 Comparator 接口?有没有一种不同的方法可以让地图使用不同的排序方法(与 class 名称中的 Comparable 接口提供的排序方法不同),而无需在初始化时将其传递给匿名 class?如果这个问题不够清楚,或者不适合这个网站,我很抱歉。
编辑:我理解 Comparable 与 Comparator 的争论以及何时使用它们。我的问题更多是关于如何使用比较器。您可以在初始化时对 Map 进行排序而不向其传递新的 Comparator 吗? class 什么时候实现这个接口是个好主意?
类 实现 Comparator
不应该做任何其他事情。
由于大多数这样的 classes 仅在一个地方使用,因此通常不命名地实现它们,即作为匿名 class 就像您在第二个示例中所做的那样。
但是,如果您希望 Comparator
可重复使用,最好为它创建一个独立的 class,例如在您的示例中将其命名为 FirstNameComparator
。
请注意,在 Java 8+ 中,使用 lambda 表达式比使用匿名 class 更容易(因为从逻辑上讲,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));
所以我正在学习 Comparator 和 Comparable,我遇到了以下问题。 我有一个 class:
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);
}
}
另一个class,Name实现了Comparable,构造函数中有first和last两个String。我不完全理解的是 Comparator 的功能,我已经阅读了 Java 文档并且我知道它用于对元素进行不同的排序而不更改名称 class 在我的示例中它也可以允许 null某些情况下的值,但我的 class 构造函数中的这个声明工作正常,我根本不需要在 PhoneBook class 中实现比较器接口:
Public PhoneBook(ArrayList<Name> names, ArrayList<Integer> phones) {
this.directory = new TreeMap<Name, Integer>(new Comparator<Name>(){
@Override
public int compare(Name o1, Name o2) {
return o1.firstName.compareTo(o2.firstName);
}
});
//other constructor code to populate map
}
并且实现了我希望它实现的功能,而不需要PhoneBook实现Comparator接口class。我的问题是 class 什么时候想要实现 Comparator 接口?有没有一种不同的方法可以让地图使用不同的排序方法(与 class 名称中的 Comparable 接口提供的排序方法不同),而无需在初始化时将其传递给匿名 class?如果这个问题不够清楚,或者不适合这个网站,我很抱歉。
编辑:我理解 Comparable 与 Comparator 的争论以及何时使用它们。我的问题更多是关于如何使用比较器。您可以在初始化时对 Map 进行排序而不向其传递新的 Comparator 吗? class 什么时候实现这个接口是个好主意?
类 实现 Comparator
不应该做任何其他事情。
由于大多数这样的 classes 仅在一个地方使用,因此通常不命名地实现它们,即作为匿名 class 就像您在第二个示例中所做的那样。
但是,如果您希望 Comparator
可重复使用,最好为它创建一个独立的 class,例如在您的示例中将其命名为 FirstNameComparator
。
请注意,在 Java 8+ 中,使用 lambda 表达式比使用匿名 class 更容易(因为从逻辑上讲,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));