对对象集合进行排序

时间:2009-07-30 11:44:48

标签: java sorting collections

如果我有一个简单的字符串列表:

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

我想有时候按名字排序,有时按年龄,有时按国家排序。

实现这一目标的最简单方法是什么?

我知道我可以实现Comparable接口,但这似乎限制我用一个特定的属性对它进行排序。

9 个答案:

答案 0 :(得分:48)

可以使用自定义比较器调用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;
  }
}

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

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
}

答案 1 :(得分:35)

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

答案 2 :(得分:17)

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

解决方案是创建以下附加类:

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

然后可以按如下方式对列表进行排序:

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

答案 3 :(得分:10)

Java 8的方法是使用List.sort,如下所示:

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

Stuart Marks的答案中引用here

  

这是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技术。

答案 4 :(得分:6)

您也可以使用apache commons beanutils中的BeanComparator,如下所示:

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

答案 5 :(得分:3)

实施3种不同类型的比较器。

您可以将比较器添加到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();
        }
    });

答案 6 :(得分:2)

可以使用第二个参数调用Collections.sort方法,该参数是要使用的比较器。 创建3个比较器并在适当的时候使用您想要的比较器。

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

答案 7 :(得分:0)

我问very similar question(关于搜索而不是排序),也许有一些有用的信息(我最终使用enum来实现Comparator所以我通过了{{1}值作为比较器选择器)。

答案 8 :(得分:0)

使用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());