简体   繁体   English

java比较器,如何按整数排序?

[英]java comparator, how to sort by integer?

Im trying to learn comparator in java and I have found this great example online, my question is how would this code be changed so that the pet names are ordered by age and in descending order so that the oldest is first and youngest is last? 我试图在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() + ", ");
}
}

Simply changing 简单地改变

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

to

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

should sort them in the reverse order of age if that is what you are looking for. 如果你正在寻找的话,应该按照年龄的相反顺序对它们进行排序。

Update: 更新:

@Arian is right in his comments, one of the accepted ways of declaring a comparator for a dog would be where you declare it as a public static final field in the class itself. @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);
    }

}

You could then use it any where in your code where you would like to compare dogs as follows: 然后,您可以在代码中的任何位置使用它,如下所示:

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

Another important thing to remember when implementing Comparable is that it is important that compareTo performs consistently with equals. 在实现Comparable时要记住的另一个重要事项是compareTo与equals一致执行非常重要。 Although it is not required, failing to do so could result in strange behaviour on some collections such as some implementations of Sets. 尽管不是必需的,但如果不这样做可能会导致某些集合出现奇怪的行为,例如集合的某些实现。 See this post for more information on sound principles of implementing compareTo. 有关实施compareTo的合理原则的更多信息,请参阅文章。

Update 2: Chris is right, this code is susceptible to overflows for large negative values of age. 更新2:克里斯是对的,这个代码很容易因年龄大的负值而溢出。 The correct way to implement this in Java 7 and up would be Integer.compare(d.age, d1.age) instead of d.age - d1.age . 在Java 7及更高版本中实现此功能的正确方法是Integer.compare(d.age, d1.age)而不是d.age - d1.age

Update 3: With Java 8, your Comparator could be written a lot more succinctly as: 更新3:使用Java 8,您的比较器可以更简洁地编写为:

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

The syntax for Collections.sort stays the same, but compare can be written as Collections.sort的语法保持不变,但compare可以写为

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

Just replace: 只需更换:

return d.age - d1.age;

By: 通过:

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

Or invert to reverse the list: 或反转以反转列表:

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

EDIT: 编辑:

Fixed the "memory problem". 修正了“记忆问题”。
Indeed, the better solution is change the age field in the Dog class to Integer , because there many benefits, like the null possibility... 实际上,更好的解决方案是将Dog类中的age字段更改为Integer ,因为有许多好处,例如null可能性......

public class DogAgeComparator implements Comparator<Dog> {
    public int compare(Dog o1, Dog o2) {
        return Integer.compare(o1.getAge(), o2.getId());
    }
}

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

Comparator.comparingInt(Dog::getDogAge).reversed();

One simple way is 一个简单的方法是

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

On a side note, Dog should really not implement Comparator . 另外,Dog应该不会实现Comparator It means you have to do strange things like 这意味着你必须做一些奇怪的事情

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

Rather you should make Compartors as separate classes. 相反,您应该将Compartors作为单独的类。

eg. 例如。

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

This has the added benefit that you can use the name of the class to say how the Comparator will sort the list. 这样做的另一个好处是,您可以使用类的名称来说明比较器如何对列表进行排序。 eg. 例如。

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

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

You should also not not have Dog implement Comparable . 你也应该没有Dog实现Comparable The Comparable interface is used to denote that there is some inherent and natural way to order these objects (such as for numbers and strings). Comparable接口用于表示有一些固有的和自然的方式来订购这些对象(例如数字和字符串)。 Now this is not the case for Dog objects as sometimes you may wish to sort by age and sometimes you may wish to sort by name. 现在这不是Dog对象的情况,因为有时您可能希望按年龄排序,有时您可能希望按名称排序。

If you have access to the Java 8 Comparable API, Comparable.comparingToInt() may be of use. 如果您可以访问Java 8 Comparable API,则可以使用Comparable.comparingToInt() (See Java 8 Comparable Documentation ). (参见Java 8 Comparable Documentation )。

For example, a Comparator<Dog> to sort Dog instances descending by age could be created with the following: 例如,可以使用以下命令创建Comparator<Dog>以按年龄降序排序Dog实例:

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

The function take a lambda mapping T to Integer , and creates an ascending comparator. 该函数将lambda映射TInteger ,并创建一个升序比较器。 The chained function .reversed() turns the ascending comparator into a descending comparator. 链接函数.reversed()将升序比较器转换为降序比较器。

Note: while this may not be useful for most versions of Android out there, I came across this question while searching for similar information for a non-Android Java application. 注意:虽然这可能对大多数Android版本没有用,但我在搜索非Android Java应用程序的类似信息时遇到了这个问题。 I thought it might be useful to others in the same spot to see what I ended up settling on. 我认为在同一地点的其他人看看我最终解决的问题可能会有用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM