用 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 个人进行排序:
- 首先显示 favorite=true 的项目
- 计数 > 0 的第二个显示项目
- 最后显示计数 == 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(...)
按多个属性排序。对于首先对收藏夹进行排序,您可以按该属性排序,但随后必须反转结果,因为 false
在 true
之前排序。假设您只想按 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);
我有collection个人:
class Person {
public String name;
public int count;
public boolean favorite;
// getters / setters ...
}
我想按以下方式对 collection 个人进行排序:
- 首先显示 favorite=true 的项目
- 计数 > 0 的第二个显示项目
- 最后显示计数 == 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(...)
按多个属性排序。对于首先对收藏夹进行排序,您可以按该属性排序,但随后必须反转结果,因为 false
在 true
之前排序。假设您只想按 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);