可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
This question already has an answer here:
-
Sorting an ArrayList of objects using a custom sorting order
10 answers
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:
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.
回答1:
Implement the Comparator interface (once for each different sort order) and use the Collections.sort() method that takes a Comparator as additional parameter.
回答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):
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:
personList.sort(Comparator.comparing(Person::getName));
To quote Stuart Marks in his answer over here.
This is the big advantage of the List.sort(cmp)
extension method over Collections.sort(list, cmp)
. It might seem that this is merely a small syntactic advantage being able to write myList.sort(cmp)
instead of Collections.sort(myList, cmp)
. The difference is that myList.sort(cmp)
, being an interface extension method, can be overridden by the specific List
implementation. For example, ArrayList.sort(cmp)
sorts the list in-place using Arrays.sort()
whereas the default implementation implements the old copyout-sort-copyback technique.
回答5:
You could also use the BeanComparator from apache commons beanutils, like this:
Collections.sort(personList, new BeanComparator(\"name\"));
回答6:
Implement 3 different types of Comparator.
you can add the comparator to the sort command. The comparator you define, will sort the elements by name, age, or what ever.
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(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).
回答9:
Using lambdaj ( http://code.google.com/p/lambdaj/ ) you can achieve what you\'re asking in the following way:
sort(personList, on(Person.class).getName());
sort(personList, on(Person.class).getAge());
sort(personList, on(Person.class).getCountry());