bra*_*orm 5 java sorting comparable comparator
"您将如何按其ID或名称对员工对象的集合进行排序".为此,我们可以使用两个接口,即,Comparator and Comparable.
这似乎是常见的面试问题之一
但我没有看到为什么我应该使用它们来排序员工对象的原因
我一直在思考comparator那些Comparable做不到的事情.我理解,如果对象(被比较的实例变量)具有自然顺序,那么这comparable是正确的选择.但是如果需要自定义排序(例如字符串长度)那么可以comparator.
在这里写一个我的观点,comparator如果他想要通过其他一些标准对数据进行排序,则只需要客户端.例如,我将实现一个使用Employee class排序.但是如果客户端希望按(名称)对Employee对象进行排序,他将实现为具体类或匿名排序.这里有什么我想念的吗?idcomparable interfaceStringcomparator
例如,在下面的代码中,对于Person对象,我的compareTo方法,比较年龄并对其进行排序.在compare方法中,我使用String length(人名)进行排序.从理论上讲,我可以在compareTo方法中完成这两个方法,如下所示.
最后,除了其他方面之外还有其他任何好处,我已经用两种方式实现了比较器1.作为一个静态方法,它被注释掉2.作为主方法中的匿名对象(?)被注释掉3. make一个实现比较器并在collections.sort()中调用该类实例的新类 - 我还没有在这里完成
(The commented-out parts of the code works. They are just different implementations)
mport java.util.Collections;
import java.util.Comparator;
import java.util.*;
public class PersonComparator implements Comparable{
private String name;
private int age;
public PersonComparator(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "name=" + name + ", age=" + age;
}
/*@Override
public int compareTo(Object obj) {
if (!(obj instanceof PersonComparator)) {
throw new ClassCastException("Invalid object");
}
PersonComparator p2 = (PersonComparator)obj;
return this.age-p2.age;
}*/
/*Alternative CompareTo that checks for both age and name*/
public int compareTo(Object obj) {
if (!(obj instanceof PersonComparator)) {
throw new ClassCastException("Invalid object");
}
PersonComparator p2 = (PersonComparator)obj;
if (this.age!=p2.age){
return this.age-p2.age;
}
else {
return (this.name.length()-p2.name.length());
}
}
/*public static Comparator nameLengthComparator
= new Comparator() {
@Override
public int compare(Object obj1, Object obj2) {
if (!(obj1 instanceof PersonComparator) || !(obj2 instanceof PersonComparator)){
throw new ClassCastException("Invalid object");
}
else {
PersonComparator p1 = (PersonComparator)obj1;
PersonComparator p2 = (PersonComparator)obj2;
return p1.name.length()-p2.name.length();
}
}
};*/
public static void main(String[] args){
PersonComparator p1 = new PersonComparator("Alexander", 45);
PersonComparator p2 = new PersonComparator("Pat", 27);
PersonComparator p3 = new PersonComparator("Zacky", 45);
PersonComparator p4 = new PersonComparator("Rake", 34);
List<PersonComparator> list = new ArrayList<PersonComparator>();
list.add(p1);
list.add(p2);
list.add(p3);
list.add(p4);
System.out.println("Before sorting "+ list);
Collections.sort(list);
//System.out.println("After sorting by age "+ list);
//System.out.println("Before sorting "+ list);
//Collections.sort(list, nameLengthComparator);
System.out.println("After sorting by name length "+ list);
/*Collections.sort(list, new Comparator<PersonComparator>() {
@Override
public int compare(PersonComparator p1, PersonComparator p2) {
return p1.name.length()-p2.name.length();
}
}
);*/
System.out.println("After sorting by name length "+ list);
}
}
Run Code Online (Sandbox Code Playgroud)
谢谢
比较器的优势是什么?
它不是"优越的".只是两个接口以不同的方式(大致)做同样的事情.在Comparable订购逻辑位于订购对象的情况下.在这种Comparator情况下,逻辑与声明的对象位于不同的类中.
但我没有看到为什么我应该使用它们来排序员工对象的原因
如果您需要能够将对象排序为不同的顺序,那么使用两者的唯一情况是有意义的.然后,您可以将相关类声明为实现Comparable"自然"订单,并使用Comparator对象来实现其他订单.
顺便说一下,比较器可能不应该实现Comparable,反之亦然.
如果比较器实现Comparable意味着您正在尝试对比较器对象本身的实例进行排序......
你的PersonComparator班级名不副实.它应该真的被称为Person.
你能否在答案中澄清一下我们已经有
equals()来自Object类的方法然后为什么Comparator界面equals()再次促进该方法?
一些要点:
你似乎仍然是混乱的目的Comparable和Comparator.对象equals上的方法Comparator将比较器与其他比较器进行比较!
该equals方法告诉您两个对象是否相等...而不是哪一个是第一个.
其原因Comparator覆盖equals是仅仅让他们能够清楚地记录了什么equals(Object),当你把它叫做上确实Comparator对象.(实际行为完全符合Object.equals(Object)......但他们显然认为有必要这样做,因为程序员反复得到方法的语义错误.)
Comparable 接口该Comparable接口定义了一个类型的自然排序.假设您有一个String或多个Integer对象的列表; 你可以将该列表传递给
Collections.sort(list);
Run Code Online (Sandbox Code Playgroud)
你将有一个排序列表.怎么样?因为String并且Integer实现Comparable接口和接口的实现Comparable提供了自然的顺序.它就像类定义那样 - " 如果找到我的类型的对象集合,请根据我在compareTo方法中定义的策略对它们进行排序 ".
现在,当您定义自己的类型时,可以通过实现接口来定义类的对象的自然顺序Comparable.有关对象排序的更多信息,请参阅Java文档.
Comparator 接口该Comparator接口描述了如何为对象排序定义自定义策略.假设我们有一个简单的Person类型如下:
public class Person {
String name;
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
Run Code Online (Sandbox Code Playgroud)
现在,通过实现Comparator界面,您可以编写不同的策略来订购Person类型的实例.例如,考虑Person下面给出的两个对象排序策略:
class StrategyOne implements Comparator<Person> {
@Override
public int compare(Person p1, Person p2) {
return p1.getName().length() - p2.getName().length();
}
}
class StrategyTwo implements Comparator<Person> {
@Override
public int compare(Person p1, Person p2) {
return p1.getName().compareTo(p2.getName());
}
}
Run Code Online (Sandbox Code Playgroud)
在这里,StrategyOne将责令Person基于其名称的长度对象,StrategyTwo订货会Person根据他们的名字的字典顺序对象.
Comparator如您所见,具体策略类是无状态的,因此所有实例在功能上都是等效的.因此,我们只需要任何具体策略类的单个实例.因此,它应该是一个单身人士.每次执行调用时,使用匿名类将创建一个新实例.考虑将对象存储在私有静态final字段中,并使用静态工厂方法重新访问它们.例如,您可以重复使用以下两种具体策略:
class Strategies {
private static final Comparator<Person> PERSON_NAME_LENGTH_COMPARATOR = new StrategyOne();
private static final Comparator<Person> PERSON_NAME_LEXICAL_COMPARATOR = new StrategyTwo();
public static Comparator<Person> personNameLengthComparator(){
return PERSON_NAME_LENGTH_COMPARATOR;
}
public static Comparator<Person> personNameLexicalComparator(){
return PERSON_NAME_LEXICAL_COMPARATOR;
}
}
Run Code Online (Sandbox Code Playgroud)
总而言之,Comparable接口用于定义类的自然顺序,Comparator接口用于定义对象排序的特定策略.
| 归档时间: |
|
| 查看次数: |
6326 次 |
| 最近记录: |