用 1.8 jdk 按多个字段对 objects 的排序列表

sorting list of objects by multiple fields with 1.8 jdk

我有collection个人:

class Person {
    public String name;
    public int count;
    public boolean favorite;

    // getters / setters ...
}

我想按以下方式对 collection 个人进行排序:

  1. 首先显示 favorite=true 的项目
  2. 计数 > 0 的第二个显示项目
  3. 最后显示计数 == 0 的项目

如何使用 1.8 JDK 中的比较器编写此条件并检索预期结果?

假设你想对你的人员进行排序而不是过滤他们,你可以执行以下操作:

class Person implements Comparable<Person>
{
  ...

  @Override
  int compareTo(Person person)
  {
    // Maye not specified
    if (person == null)
      return (1);

    // Compare 'favorite'
    // Favorites first, so flag=true means smaller
    if (this.favorite && (!person.favorite))
      return (-1);
    else if ((!this.favorite) && person.favorite)
      return (1);

    // Compare 'count'
    // Having count > 0 first, so count=0 means greater
    // Assuming count is never negative
    if ((this.count == 0) && (person.count > 0))
      return (1);
    if ((this.count > 0) && (person.count == 0))
      return (-1);

    // At this point, both persons have the same 'favorite' flag
    // And both have either count=0 or count>0
    // Order by name in that case
    return (this.name.compareTo(person.name));

  } // compareTo

} // class Person

之后,对你的人进行排序:

List<Person> my_persons;
my_persons = ....
Collections.sort(my_persons);

您可以使用 Comparator.comparing(...).thenComparing(...) 按多个属性排序。对于首先对收藏夹进行排序,您可以按该属性排序,但随后必须反转结果,因为 falsetrue 之前排序。假设您只想按 count 是否为 > 0 进行排序,而不是按计数的实际值进行排序:

List<Person> persons = Arrays.asList(
        new Person("p1", 2, true),
        new Person("p2", 0, false),
        new Person("p3", 0, true),
        new Person("p4", 1, false),
        new Person("p5", 3, true));

persons.stream().sorted(Comparator
            .comparing(Person::isFavorite).reversed()
            .thenComparing(p -> p.getCount() == 0))
    .forEach(System.out::println);

结果:

Person(name=p1, count=2, favorite=true)
Person(name=p5, count=3, favorite=true)
Person(name=p3, count=0, favorite=true)
Person(name=p4, count=1, favorite=false)
Person(name=p2, count=0, favorite=false)

注意最后的count == 0条件是多余的(假设count不能< 0

或者直接按count排序,最后反转一次;这将在示例中将 p5 排序在 p1 之前:

persons.stream().sorted(Comparator
            .comparing(Person::isFavorite)
            .thenComparing(Person::getCount).reversed())
    .forEach(System.out::println);