我试图在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() + ", ");
}
}
答案 0 :(得分:89)
简单地改变
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一致执行非常重要。尽管不是必需的,但如果不这样做可能会导致某些集合出现奇怪的行为,例如集合的某些实现。有关实施compareTo的合理原则的更多信息,请参阅this帖子。
更新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);
}
答案 1 :(得分:19)
只需替换:
return d.age - d1.age;
人:
return ((Integer)d.age).compareTo(d1.age);
或反转以反转列表:
return ((Integer)d1.age).compareTo(d.age);
修改强>
修正了“记忆问题”
实际上,更好的解决方案是将age
类中的Dog
字段更改为Integer
,因为有许多好处,例如null
可能性......
答案 2 :(得分:16)
public class DogAgeComparator implements Comparator<Dog> {
public int compare(Dog o1, Dog o2) {
return Integer.compare(o1.getAge(), o2.getId());
}
}
答案 3 :(得分:9)
从Java 8开始,您可以使用:
upvar 1
答案 4 :(得分: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
相反,你应该将Compartors作为单独的类。
例如
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对象的情况,因为有时您可能希望按年龄排序,有时您可能希望按名称排序。