Java 使用 Comparator- 降序排序(用户定义的类)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1946668/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 01:41:56  来源:igfitidea点击:

Sorting using Comparator- Descending order (User defined classes)

java

提问by Manoj

I want to sort my objects in descending order using comparator.

我想使用比较器按降序对我的对象进行排序。

class Person {
 private int age;
}

Here I want to sort a array of Person objects.

在这里,我想对一组 Person 对象进行排序。

How can I do this?

我怎样才能做到这一点?

采纳答案by Lucky

You can do the descending sort of a user-defined class this way overriding the compare()method,

您可以通过这种方式覆盖compare()方法,对用户定义的类进行降序排序,

Collections.sort(unsortedList,new Comparator<Person>() {
    @Override
    public int compare(Person a, Person b) {
        return b.getName().compareTo(a.getName());
    }
});

Orby using Collection.reverse()to sort descending as user Princementioned in his comment.

或者通过使用Collection.reverse()降序排序为用户Prince他的评论中提到的。

And you can do the ascending sort like this,

你可以像这样进行升序排序,

Collections.sort(unsortedList,new Comparator<Person>() {
    @Override
    public int compare(Person a, Person b) {
        return a.getName().compareTo(b.getName());
    }
});

Replace the above code with a Lambda expression(Java 8 onwards) we get concise:

用 Lambda 表达式(Java 8 以后)替换上面的代码,我们得到简洁:

Collections.sort(personList, (Person a, Person b) -> b.getName().compareTo(a.getName()));

As of Java 8, List has sort()method which takes Comparatoras parameter(more concise) :

从 Java 8 开始,List 有sort()方法,它以Comparator作为参数(更简洁):

personList.sort((a,b)->b.getName().compareTo(a.getName()));

Here aand bare inferred as Person type by lambda expression.

这里ab被 lambda 表达式推断为 Person 类型。

回答by Thomas Jung

String[] s = {"a", "x", "y"};
Arrays.sort(s, new Comparator<String>() {

    @Override
    public int compare(String o1, String o2) {
        return o2.compareTo(o1);
    }
});
System.out.println(Arrays.toString(s));

-> [y, x, a]

Now you have to implement the Comparator for your Person class. Something like (for ascending order): compare(Person a, Person b) = a.id < b.id ? -1 : (a.id == b.id) ? 0 : 1or Integer.valueOf(a.id).compareTo(Integer.valueOf(b.id)).

现在你必须为你的 Person 类实现 Comparator 。类似(升序):compare(Person a, Person b) = a.id < b.id ? -1 : (a.id == b.id) ? 0 : 1Integer.valueOf(a.id).compareTo(Integer.valueOf(b.id))

To minimize confusion you should implement an ascending Comparator and convert it to a descending one with a wrapper (like this) new ReverseComparator<Person>(new PersonComparator()).

为了尽量减少混淆,您应该实现一个升序比较器并将其转换为一个带有包装器的降序比较器(像这样new ReverseComparator<Person>(new PersonComparator())

回答by Robert Christie

The java.util.Collections class has a sort method that takes a list and a custom Comparator. You can define your own Comparator to sort your Person object however you like.

java.util.Collection中的类有一种方法,它接受一个列表和一个自定义的比较。你可以定义你自己的 Comparator 来按照你喜欢的方式对你的 Person 对象进行排序。

回答by Shamik

package com.test;

import java.util.Arrays;

public class Person implements Comparable {

private int age;

private Person(int age) {
    super();
    this.age = age;
}

public int getAge() {
    return age;
}

public void setAge(int age) {
    this.age = age;
}

@Override
public int compareTo(Object o) {
    Person other = (Person)o;
    if (this == other)
        return 0;
    if (this.age < other.age) return 1;
    else if (this.age == other.age) return 0;
    else return -1;

}

public static void main(String[] args) {

    Person[] arr = new Person[4];
    arr[0] = new Person(50);
    arr[1] = new Person(20);
    arr[2] = new Person(10);
    arr[3] = new Person(90);

    Arrays.sort(arr);

    for (int i=0; i < arr.length; i++ ) {
        System.out.println(arr[i].age);
    }
}

}

Here is one way of doing it.

这是一种方法。

回答by Andreas Dolk

I would create a comparator for the person class that can be parametrized with a certain sorting behaviour. Here I can set the sorting order but it can be modified to allow sorting for other person attributes as well.

我将为 person 类创建一个比较器,该比较器可以通过某种排序行为进行参数化。在这里我可以设置排序顺序,但也可以修改它以允许对其他人员属性进行排序。

public class PersonComparator implements Comparator<Person> {

  public enum SortOrder {ASCENDING, DESCENDING}

  private SortOrder sortOrder;

  public PersonComparator(SortOrder sortOrder) {
    this.sortOrder = sortOrder;
  }

  @Override
  public int compare(Person person1, Person person2) {
    Integer age1 = person1.getAge();
    Integer age2 = person2.getAge();
    int compare = Math.signum(age1.compareTo(age2));

    if (sortOrder == ASCENDING) {
      return compare;
    } else {
      return compare * (-1);
    }
  }
}

(hope it compiles now, I have no IDE or JDK at hand, coded 'blind')

(希望它现在可以编译,我手头没有 IDE 或 JDK,编码为“盲”)

Edit

编辑

Thanks to Thomas, edited the code. I wouldn't say that the usage of Math.signum is good, performant, effective, but I'd like to keep it as a reminder, that the compareTo method can return any integer and multiplying by (-1) will fail if the implementation returns Integer.MIN_INTEGER... And I removed the setter because it's cheap enough to construct a new PersonComparator just when it's needed.

感谢 Thomas,编辑了代码。我不会说 Math.signum 的使用是好的、高性能的、有效的,但我想保留它作为提醒,compareTo 方法可以返回任何整数并且乘以 (-1) 将失败,如果实现返回Integer.MIN_INTEGER...我删除了setter,因为它足够便宜,可以在需要时构造一个新的PersonComparator。

But I keep the boxing because it shows that I rely on an existing Comparable implementation. Could have done something like Comparable<Integer> age1 = new Integer(person1.getAge());but that looked too ugly. The idea was to show a pattern which could easily be adapted to other Person attributes, like name, birthday as Date and so on.

但是我保留了拳击,因为它表明我依赖于现有的 Comparable 实现。本来可以做类似的事情,Comparable<Integer> age1 = new Integer(person1.getAge());但那看起来太丑了。这个想法是为了展示一个可以很容易地适应其他人属性的模式,比如姓名、生日作为日期等等。

回答by finnw

Using Google Collections:

使用谷歌收藏:

class Person {
 private int age;

 public static Function<Person, Integer> GET_AGE =
  new Function<Person, Integer> {
   public Integer apply(Person p) { return p.age; }
  };

}

public static void main(String[] args) {
 ArrayList<Person> people;
 // Populate the list...

 Collections.sort(people, Ordering.natural().onResultOf(Person.GET_AGE).reverse());
}

回答by camickr

For whats its worth here is my standard answer. The only thing new here is that is uses the Collections.reverseOrder(). Plus it puts all suggestions into one example:

对于这里的价值是什么是我的标准答案。这里唯一的新东西是使用 Collections.reverseOrder()。此外,它还将所有建议整合到一个示例中:

/*
**  Use the Collections API to sort a List for you.
**
**  When your class has a "natural" sort order you can implement
**  the Comparable interface.
**
**  You can use an alternate sort order when you implement
**  a Comparator for your class.
*/
import java.util.*;

public class Person implements Comparable<Person>
{
    String name;
    int age;

    public Person(String name, int age)
    {
        this.name = name;
        this.age = age;
    }

    public String getName()
    {
        return name;
    }

    public int getAge()
    {
        return age;
    }

    public String toString()
    {
        return name + " : " + age;
    }

    /*
    **  Implement the natural order for this class
    */
    public int compareTo(Person p)
    {
        return getName().compareTo(p.getName());
    }

    static class AgeComparator implements Comparator<Person>
    {
        public int compare(Person p1, Person p2)
        {
            int age1 = p1.getAge();
            int age2 = p2.getAge();

            if (age1 == age2)
                return 0;
            else if (age1 > age2)
                return 1;
            else
                return -1;
        }
    }

    public static void main(String[] args)
    {
        List<Person> people = new ArrayList<Person>();
        people.add( new Person("Homer", 38) );
        people.add( new Person("Marge", 35) );
        people.add( new Person("Bart", 15) );
        people.add( new Person("Lisa", 13) );

        // Sort by natural order

        Collections.sort(people);
        System.out.println("Sort by Natural order");
        System.out.println("\t" + people);

        // Sort by reverse natural order

        Collections.sort(people, Collections.reverseOrder());
        System.out.println("Sort by reverse natural order");
        System.out.println("\t" + people);

        //  Use a Comparator to sort by age

        Collections.sort(people, new Person.AgeComparator());
        System.out.println("Sort using Age Comparator");
        System.out.println("\t" + people);

        //  Use a Comparator to sort by descending age

        Collections.sort(people,
            Collections.reverseOrder(new Person.AgeComparator()));
        System.out.println("Sort using Reverse Age Comparator");
        System.out.println("\t" + people);
    }
}