Sorting a collection of objects

JavaSortingCollections

Java Problem Overview


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.

Java Solutions


Solution 1 - Java

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
}

Solution 2 - Java

Implement the Comparator interface (once for each different sort order) and use the Collections.sort() method that takes a Comparator as additional parameter.

Solution 3 - Java

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

Solution 4 - Java

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.

Solution 5 - Java

You could also use the BeanComparator from apache commons beanutils, like this:

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

Solution 6 - Java

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

Solution 7 - Java

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) {
          ...
        }
      });

Solution 8 - Java

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).

Solution 9 - Java

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionKnut Arne VedaaView Question on Stackoverflow
Solution 1 - JavaAndreas DolkView Answer on Stackoverflow
Solution 2 - JavaMichael BorgwardtView Answer on Stackoverflow
Solution 3 - JavaKnut Arne VedaaView Answer on Stackoverflow
Solution 4 - JavaaioobeView Answer on Stackoverflow
Solution 5 - JavaJörn HorstmannView Answer on Stackoverflow
Solution 6 - JavaMarkus LausbergView Answer on Stackoverflow
Solution 7 - JavaMark BolusmjakView Answer on Stackoverflow
Solution 8 - JavaJason SView Answer on Stackoverflow
Solution 9 - JavaMario FuscoView Answer on Stackoverflow