对一组对象进行sorting

如果我有一个简单的string列表:

List<String> stringList = new ArrayList<String>(); 

我可以用它来分类:

 Collections.sort(stringList); 

但是假设我有一个Person类:

 public class Person { private String name; private Integer age; private String country; } 

和一个列表:

 List<Person> personList = new ArrayList<Person>(); 

我想按名称sorting,有时按年龄排列,有时按国家排列。

什么是最简单的方法来完成呢?

我知道我可以实现Comparable接口,但这似乎限制我sorting一个特定的属性。

实现Comparator接口(每个不同的sorting顺序一次),并使用Comparator作为附加参数的Collections.sort()方法。

可以使用自定义比较器调用Collections.sort。 并且可以实现该比较器以允许以不同的sorting顺序sorting。 下面是一个例子(对于你的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; } } 

你就这样使用它(假设人是一个领域):

 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 } 

感谢响应者。 为了他人的利益,我想包括一个完整的例子。

解决方法是创build以下附加类:

 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()); } } 

该列表可以像这样sorting:

 Collections.sort(personList, new NameComparator()); Collections.sort(personList, new AgeComparator()); Collections.sort(personList, new CountryComparator()); 

这样做的Java 8的方式是使用List.sort如下:

 personList.sort(Comparator.comparing(Person::getName)); 

在这里引用Stuart Marks的回答。

这是List.sort(cmp)扩展方法优于Collections.sort(list, cmp)的一大优点。 看起来,这只是一个小的语法优势,能够写myList.sort(cmp)而不是Collections.sort(myList, cmp) 。 不同的是,作为接口扩展方法的myList.sort(cmp) 可以被特定的List实现覆盖 。 例如, ArrayList.sort(cmp)使用Arrays.sort()就地对列表进行Arrays.sort()而默认实现实现旧的copyout-sort-copyback技术。

你也可以使用apache commons beanutils的BeanComparator,像这样:

 Collections.sort(personList, new BeanComparator("name")); 

实现3种不同types的比较器。

您可以将比较器添加到sort命令。 您定义的比较器将按名称,年龄或以往任何方式对元素进行sorting。

 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(); } }); 

Collections.sort方法可以使用第二个参数来调用,这个参数是要使用的比较器。 创build3个比较器,并在适当的时候使用你想要的。

 Collections.sort(list , new Comparator() { public int compare(Object o1, Object o2) { ... } }); 

我问了一个非常类似的问题 (关于search而不是sorting),也许有一些有用的信息(我最终使用一个enum实现Comparator所以我通过enum值作为比较select器)。

使用lambdaj( http://code.google.com/p/lambdaj/ )你可以通过以下方式实现你所要求的:

(personList,on(Person.class).getName());

(personList,on(Person.class).getAge());

(personList,on(Person.class).getCountry());