This question already has an answer here:
这个问题在这里已有答案:
- Sorting an ArrayList of objects using a custom sorting order 10 answers
使用自定义排序顺序排列对象的ArrayList 10个答案
If I have a simple list of Strings:
如果我有一个简单的字符串列表:
List<String> stringList = new ArrayList<String>();
I can sort it with:
我可以用它来分类:
Collections.sort(stringList);
But suppose I have a Person class:
但是假设我有一个Person类:
public class Person{ private String name; private Integer age; private String country;}
And a list of it:
并列出一个:
List<Person> personList = new ArrayList<Person>();
And I want to sort it sometimes by name, sometimes by age, sometimes by country.
我希望有时按名字排序,有时按年龄,有时按国家排序。
What is the easiest way to accomplish that?
最简单的方法是什么?
I know that I can implement the Comparable interface, but that seems to limit me to sort it by one specific property.
我知道我可以实现Comparable接口,但这似乎限制我按一个特定属性对其进行排序。
9 个解决方案
#1
Implement the Comparator interface (once for each different sort order) and use the Collections.sort() method that takes a Comparator as additional parameter.
实现Comparator接口(每个不同的排序顺序一次)并使用Collections.sort()方法,该方法将Comparator作为附加参数。
#2
Collections.sort can be called with a custom comparator. And that comparator can be implemented to allow sorting in different sort orders. Here's an example (for your Person model - with age as an Integer):
可以使用自定义比较器调用Collections.sort。并且可以实现该比较器以允许以不同的排序顺序进行排序。这是一个例子(对于你的Person模型 - 年龄为整数):
public class FlexiblePersonComparator implements Comparator<Person> { public enum Order {Name, Age, Country} private Order sortingBy = Name; @Override public int compare(Person person1, Person person2) { switch(sortingBy) { case Name: return person1.name.compareTo(person2.name); case Age: return person1.age.compareTo(person2.age); case Country: return person1.country.compareTo(person2.country); } throw new RuntimeException("Practically unreachable code, can't be thrown"); } public void setSortingBy(Order sortBy) { this.sortingBy = sortingBy; }}
And you use it like that (assuming persons is a field):
你就这样使用它(假设人是一个领域):
public void sortPersonsBy(FlexiblePersonComparator.Order sortingBy) { List<Person> persons = this.persons; // useless line, just for clarification FlexiblePersonComparator comparator = new FlexiblePersonComparator(); comparator.setSortingBy(sortingBy); Collections.sort(persons, comparator); // now we have a sorted list}
#3
Thanks to the responders. For the benefit of others, I'd like to include a complete example.
感谢响应者。为了他人的利益,我想提供一个完整的例子。
The solution is the create the following additional classes:
解决方案是创建以下附加类:
public class NameComparator implements Comparator<Person>{ public int compare(Person o1, Person o2) { return o1.getName().compareTo(o2.getName()); }}public class AgeComparator implements Comparator<Person>{ public int compare(Person o1, Person o2) { return o1.getAge().compareTo(o2.getAge()); }}public class CountryComparator implements Comparator<Person>{ public int compare(Person o1, Person o2) { return o1.getCountry().compareTo(o2.getCountry()); }}
The list can then be sorted like this:
然后可以按如下方式对列表进行排序:
Collections.sort(personList, new NameComparator());Collections.sort(personList, new AgeComparator());Collections.sort(personList, new CountryComparator());
#4
The Java 8 way of doing this is to use List.sort
as follows:
Java 8的方法是使用List.sort,如下所示:
personList.sort(Comparator.comparing(Person::getName));
To quote Stuart Marks in his answer over here.
引用Stuart Marks在这里的回答。
This is the big advantage of the
List.sort(cmp)
extension method overCollections.sort(list, cmp)
. It might seem that this is merely a small syntactic advantage being able to writemyList.sort(cmp)
instead ofCollections.sort(myList, cmp)
. The difference is thatmyList.sort(cmp)
, being an interface extension method, can be overridden by the specificList
implementation. For example,ArrayList.sort(cmp)
sorts the list in-place usingArrays.sort()
whereas the default implementation implements the old copyout-sort-copyback technique.这是List.sort(cmp)扩展方法优于Collections.sort(list,cmp)的一大优势。看起来这只是一个小的语法优势,能够编写myList.sort(cmp)而不是Collections.sort(myList,cmp)。区别在于myList.sort(cmp)是一个接口扩展方法,可以被特定的List实现覆盖。例如,ArrayList.sort(cmp)使用Arrays.sort()就地对列表进行排序,而默认实现实现旧的copyout-sort-copyback技术。
#5
You could also use the BeanComparator from apache commons beanutils, like this:
你也可以使用apache commons beanutils中的BeanComparator,如下所示:
Collections.sort(personList, new BeanComparator("name"));
#6
Implement 3 different types of Comparator.
实现3种不同类型的比较器。
you can add the comparator to the sort command. The comparator you define, will sort the elements by name, age, or what ever.
您可以将比较器添加到sort命令。您定义的比较器将按名称,年龄或任何内容对元素进行排序。
Collections.sort(list, new Comparator() { public int compare(Object arg0, Object arg1) { if (!(arg0 instanceof Person)) { return -1; } if (!(arg1 instanceof Person)) { return -1; } Person pers0 = (Person)arg0; Person pers1 = (Person)arg1; // COMPARE NOW WHAT YOU WANT // Thanks to Steve Kuo for your comment! return pers0.getAge() - pers1.getAge(); } });
#7
The Collections.sort method can be invoked with a second argument which is the comparator to use.Create 3 comparators and use the one you want when appropriate.
可以使用第二个参数调用Collections.sort方法,该参数是要使用的比较器。创建3个比较器并在适当时使用所需的比较器。
Collections.sort(list , new Comparator() { public int compare(Object o1, Object o2) { ... } });
#8
I asked a very similar question (about searching rather than sorting), perhaps there is some useful information (I ended up using an enum
that implements Comparator
so I pass the enum
value as a comparator selector).
我问了一个非常相似的问题(关于搜索而不是排序),也许有一些有用的信息(我最终使用了一个实现Comparator的枚举,因此我将枚举值作为比较器选择器传递)。
#9
Using lambdaj ( http://code.google.com/p/lambdaj/ ) you can achieve what you're asking in the following way:
使用lambdaj(http://code.google.com/p/lambdaj/),您可以通过以下方式实现您的要求:
sort(personList, on(Person.class).getName());
sort(personList, on(Person.class).getAge());
sort(personList, on(Person.class).getCountry());
#1
Implement the Comparator interface (once for each different sort order) and use the Collections.sort() method that takes a Comparator as additional parameter.
实现Comparator接口(每个不同的排序顺序一次)并使用Collections.sort()方法,该方法将Comparator作为附加参数。
#2
Collections.sort can be called with a custom comparator. And that comparator can be implemented to allow sorting in different sort orders. Here's an example (for your Person model - with age as an Integer):
可以使用自定义比较器调用Collections.sort。并且可以实现该比较器以允许以不同的排序顺序进行排序。这是一个例子(对于你的Person模型 - 年龄为整数):
public class FlexiblePersonComparator implements Comparator<Person> { public enum Order {Name, Age, Country} private Order sortingBy = Name; @Override public int compare(Person person1, Person person2) { switch(sortingBy) { case Name: return person1.name.compareTo(person2.name); case Age: return person1.age.compareTo(person2.age); case Country: return person1.country.compareTo(person2.country); } throw new RuntimeException("Practically unreachable code, can't be thrown"); } public void setSortingBy(Order sortBy) { this.sortingBy = sortingBy; }}
And you use it like that (assuming persons is a field):
你就这样使用它(假设人是一个领域):
public void sortPersonsBy(FlexiblePersonComparator.Order sortingBy) { List<Person> persons = this.persons; // useless line, just for clarification FlexiblePersonComparator comparator = new FlexiblePersonComparator(); comparator.setSortingBy(sortingBy); Collections.sort(persons, comparator); // now we have a sorted list}
#3
Thanks to the responders. For the benefit of others, I'd like to include a complete example.
感谢响应者。为了他人的利益,我想提供一个完整的例子。
The solution is the create the following additional classes:
解决方案是创建以下附加类:
public class NameComparator implements Comparator<Person>{ public int compare(Person o1, Person o2) { return o1.getName().compareTo(o2.getName()); }}public class AgeComparator implements Comparator<Person>{ public int compare(Person o1, Person o2) { return o1.getAge().compareTo(o2.getAge()); }}public class CountryComparator implements Comparator<Person>{ public int compare(Person o1, Person o2) { return o1.getCountry().compareTo(o2.getCountry()); }}
The list can then be sorted like this:
然后可以按如下方式对列表进行排序:
Collections.sort(personList, new NameComparator());Collections.sort(personList, new AgeComparator());Collections.sort(personList, new CountryComparator());
#4
The Java 8 way of doing this is to use List.sort
as follows:
Java 8的方法是使用List.sort,如下所示:
personList.sort(Comparator.comparing(Person::getName));
To quote Stuart Marks in his answer over here.
引用Stuart Marks在这里的回答。
This is the big advantage of the
List.sort(cmp)
extension method overCollections.sort(list, cmp)
. It might seem that this is merely a small syntactic advantage being able to writemyList.sort(cmp)
instead ofCollections.sort(myList, cmp)
. The difference is thatmyList.sort(cmp)
, being an interface extension method, can be overridden by the specificList
implementation. For example,ArrayList.sort(cmp)
sorts the list in-place usingArrays.sort()
whereas the default implementation implements the old copyout-sort-copyback technique.这是List.sort(cmp)扩展方法优于Collections.sort(list,cmp)的一大优势。看起来这只是一个小的语法优势,能够编写myList.sort(cmp)而不是Collections.sort(myList,cmp)。区别在于myList.sort(cmp)是一个接口扩展方法,可以被特定的List实现覆盖。例如,ArrayList.sort(cmp)使用Arrays.sort()就地对列表进行排序,而默认实现实现旧的copyout-sort-copyback技术。
#5
You could also use the BeanComparator from apache commons beanutils, like this:
你也可以使用apache commons beanutils中的BeanComparator,如下所示:
Collections.sort(personList, new BeanComparator("name"));
#6
Implement 3 different types of Comparator.
实现3种不同类型的比较器。
you can add the comparator to the sort command. The comparator you define, will sort the elements by name, age, or what ever.
您可以将比较器添加到sort命令。您定义的比较器将按名称,年龄或任何内容对元素进行排序。
Collections.sort(list, new Comparator() { public int compare(Object arg0, Object arg1) { if (!(arg0 instanceof Person)) { return -1; } if (!(arg1 instanceof Person)) { return -1; } Person pers0 = (Person)arg0; Person pers1 = (Person)arg1; // COMPARE NOW WHAT YOU WANT // Thanks to Steve Kuo for your comment! return pers0.getAge() - pers1.getAge(); } });
#7
The Collections.sort method can be invoked with a second argument which is the comparator to use.Create 3 comparators and use the one you want when appropriate.
可以使用第二个参数调用Collections.sort方法,该参数是要使用的比较器。创建3个比较器并在适当时使用所需的比较器。
Collections.sort(list , new Comparator() { public int compare(Object o1, Object o2) { ... } });
#8
I asked a very similar question (about searching rather than sorting), perhaps there is some useful information (I ended up using an enum
that implements Comparator
so I pass the enum
value as a comparator selector).
我问了一个非常相似的问题(关于搜索而不是排序),也许有一些有用的信息(我最终使用了一个实现Comparator的枚举,因此我将枚举值作为比较器选择器传递)。
#9
Using lambdaj ( http://code.google.com/p/lambdaj/ ) you can achieve what you're asking in the following way:
使用lambdaj(http://code.google.com/p/lambdaj/),您可以通过以下方式实现您的要求:
sort(personList, on(Person.class).getName());
sort(personList, on(Person.class).getAge());
sort(personList, on(Person.class).getCountry());