48

我试图在java中学习比较器,我在网上找到了这个很好的例子,我的问题是如何更改此代码,以便宠物名称按年龄和降序排列,以便最老的在前,最年轻的在后?

class Dog implements Comparator<Dog>, Comparable<Dog>{
private String name;
private int age;
Dog(){
}

Dog(String n, int a){
  name = n;
  age = a;
}

public String getDogName(){
  return name;
}

public int getDogAge(){
  return age;
}

// Overriding the compareTo method
public int compareTo(Dog d){
  return (this.name).compareTo(d.name);
}

// Overriding the compare method to sort the age 
public int compare(Dog d, Dog d1){
  return d.age - d1.age;
}
}

public class Example{
public static void main(String args[]){
  // Takes a list o Dog objects
  List<Dog> list = new ArrayList<Dog>();

  list.add(new Dog("Shaggy",3));
  list.add(new Dog("Lacy",2));
  list.add(new Dog("Roger",10));
  list.add(new Dog("Tommy",4));
  list.add(new Dog("Tammy",1));
  Collections.sort(list);// Sorts the array list

  for(Dog a: list)//printing the sorted list of names
     System.out.print(a.getDogName() + ", ");

  // Sorts the array list using comparator
  Collections.sort(list, new Dog());
  System.out.println(" ");
  for(Dog a: list)//printing the sorted list of ages
     System.out.print(a.getDogName() +"  : "+
     a.getDogAge() + ", ");
}
}
4

6 回答 6

102

简单地改变

public int compare(Dog d, Dog d1) {
  return d.age - d1.age;
}

public int compare(Dog d, Dog d1) {
  return d1.age - d.age;
}

如果这是您要查找的内容,则应按年龄的相反顺序对它们进行排序。

更新:

@Arian 在他的评论中是正确的,为狗声明比较器的一种公认方法是将其声明为类本身中的公共静态最终字段。

class Dog implements Comparable<Dog> {
    private String name;
    private int age;

    public static final Comparator<Dog> DESCENDING_COMPARATOR = new Comparator<Dog>() {
        // Overriding the compare method to sort the age
        public int compare(Dog d, Dog d1) {
            return d.age - d1.age;
        }
    };

    Dog(String n, int a) {
        name = n;
        age = a;
    }

    public String getDogName() {
        return name;
    }

    public int getDogAge() {
        return age;
    }

    // Overriding the compareTo method
    public int compareTo(Dog d) {
        return (this.name).compareTo(d.name);
    }

}

然后,您可以在代码中任何您想比较狗的地方使用它,如下所示:

// Sorts the array list using comparator
Collections.sort(list, Dog.DESCENDING_COMPARATOR);

实现 Comparable 时要记住的另一件重要事情是 compareTo 与 equals 一致地执行是很重要的。尽管不是必需的,但如果不这样做可能会导致某些集合出现奇怪的行为,例如 Set 的某些实现。有关实现 compareTo 的合理原则的更多信息,请参阅这篇文章。

更新 2: 克里斯是对的,此代码容易因年龄的大负值而溢出。在 Java 7 及更高版本中实现此功能的正确方法是Integer.compare(d.age, d1.age)代替d.age - d1.age.

更新 3: 使用 Java 8,您的 Comparator 可以更简洁地编写为:

public static final Comparator<Dog> DESCENDING_COMPARATOR = 
    Comparator.comparing(Dog::getDogAge).reversed();

的语法Collections.sort保持不变,但compare可以写成

public int compare(Dog d, Dog d1) {
    return DESCENDING_COMPARATOR.compare(d, d1);
}
于 2012-05-22T20:42:27.303 回答
28
public class DogAgeComparator implements Comparator<Dog> {
    public int compare(Dog o1, Dog o2) {
        return Integer.compare(o1.getAge(), o2.getId());
    }
}
于 2015-05-13T07:49:31.030 回答
21

只需更换:

return d.age - d1.age;

经过:

return ((Integer)d.age).compareTo(d1.age);

或反转以反转列表:

return ((Integer)d1.age).compareTo(d.age);

编辑:

修复了“内存问题”。
事实上,更好的解决方案是将类中的age字段更改为,因为有很多好处,比如可能性......DogIntegernull

于 2012-05-22T20:43:30.357 回答
21

从 Java 8 开始,您可以使用:

Comparator.comparingInt(Dog::getDogAge).reversed();
于 2017-04-19T13:59:22.383 回答
4

一种简单的方法是

Comparator<Dog> ageAscendingComp = ...;
Comparator<Dog> ageDescendingComp = Collections.reverseOrder(ageAscendingComp);
// then call the sort method

另一方面,Dog 真的不应该实现Comparator. 这意味着你必须做一些奇怪的事情,比如

Collections.sort(myList, new Dog("Rex", 4));
// ^-- why is a new dog being made? What are we even sorting by?!
Collections.sort(myList, myList.get(0));
// ^-- or perhaps more confusingly

相反,您应该将比较器作为单独的类。

例如。

public class DogAgeComparator implments Comparator<Dog> {
    public int compareTo(Dog d1, Dog d2) {
        return d1.getAge() - d2.getAge();
    }
}

这有一个额外的好处,您可以使用类的名称来说明比较器将如何对列表进行排序。例如。

Collections.sort(someDogs, new DogNameComparator());
// now in name ascending order

Collections.sort(someDogs, Collections.reverseOrder(new DogAgeComparator()));
// now in age descending order

你也不应该没有 Dog 工具Comparable。该Comparable接口用于表示对这些对象(例如数字和字符串)进行排序有一些固有的和自然的方式。现在这不是 Dog 对象的情况,因为有时您可能希望按年龄排序,有时您可能希望按名称排序。

于 2012-05-22T21:03:25.827 回答
2

如果您有权访问 Java 8 Comparable API,Comparable.comparingToInt()可能会有所帮助。(请参阅Java 8 可比文档)。

例如,可以使用以下命令创建按年龄降序对实例Comparator<Dog>进行排序:Dog

Comparable.comparingToInt(Dog::getDogAge).reversed();

该函数将 lambda 映射TInteger,并创建一个升序比较器。链式函数.reversed()将升序比较器转换为降序比较器。

注意:虽然这对于大多数版本的 Android 可能没有用,但我在为非 Android Java 应用程序搜索类似信息时遇到了这个问题。我认为这可能对同一地点的其他人有用,看看我最终解决了什么。

于 2016-08-15T23:24:07.210 回答