Sort List in Java using Collections.sort(List)

In this tutorial, I will describe sorting list in java using Collections.sort(List). Here are some nice animations for sorting. I will be showing examples for
1. Sorting objects that implement Comparable
2. Sorting objects that don’t implement Comparable

Sorting objects that implement Comparable

We can sort  java.util.List using a java utility class java.util.Collections. We will use a static method  sort(List) of the java.util.Collections. From Java docs of Collections.sort(List) method, some points that can help you understand what this method does:

 “Sorts the specified list into ascending order, according to the natural ordering of its elements. All elements in the list must implement the Comparable interface. Furthermore, all elements in the list must be mutually comparable (that is, e1.compareTo(e2) must not throw a ClassCastException for any elements e1 and e2 in the list).
This sort is guaranteed to be stable: equal elements will not be reordered as a result of the sort.
The specified list must be modifiable, but need not be resizable.”

Let us jump directly to the example now. This is a very simple example where i am sorting a list of Strings. First I sort the list in ascending order and then in the descending order. You will note that the this way of sort doesn’t generate a new List but sorts the same list. So by using this way of sorting you will loose the original ordering of list. I have also added in the example how to keep the original order. You can sort all Primitive Wrapper classes with this example like Integer, Long because they all implement Comparable interface.
And when I am sorting in the descending order, I am using Collections.reverseOrder() as an argument to Collections.sort. Collections.reverseOrder() returns the Comparator that imposes the reverse of the natural ordering on a collection of objects that implement the Comparable interface. 

package com.programtak.sort;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
 * This program sorts a list of Strings in ascending and descending order.
 *   
 * @author programtak
 *
 */
public class SortExample {
 
 private List<String> namesList = Arrays.asList("Kevin", "Brian" , "Steve", "Bill", "Obama");
 
 public static void main(String[] args) {
  SortExample sortExample = new SortExample();
  System.out.println("Before sorting:" + sortExample.namesList);
  
  sortExample.sortList(sortExample.namesList);
  System.out.println("List in ascending order:" + sortExample.namesList);
  
  sortExample.reverseSortList(sortExample.namesList);
  System.out.println("List in descending orde :" + sortExample.namesList);
  
  // sort a new list and don't modify the order of original list
  List<String> keepOriginalOrderList = Arrays.asList("Kevin", "Brian" , "Steve", "Bill", "Obama");
  List<String> sortedList = sortExample.sortListWithoutModifyingOriginalList(keepOriginalOrderList);
  System.out.println("List has preserved order :" + keepOriginalOrderList);
  System.out.println("New sorted list :" + sortedList);
 }
 
 
 /**
  * This method makes it obvious that any object that extends comparable can be sorted.
  * @param list - list to be sorted
  */
 private <E extends Comparable<E>> void sortList(List<E> list){
  Collections.sort(list);
 }
 
 /**
  * This method makes it obvious that any object that extends comparable can be sorted.
  * @param list - list to be reverse sorted
  */
 private <E extends Comparable<E>> void reverseSortList(List<E> list){
  Collections.sort(list, Collections.reverseOrder());
 }
 
 
 /**
  * This method preserves the original List ordering. And returns a new sorted list 
  * @param list - list to be sorted but not modified
  */
 private <E extends Comparable<E>> List<E> sortListWithoutModifyingOriginalList(List<E> list){
  List<E> newList = new ArrayList<E>(list);
  Collections.sort(newList);
  return newList;
 }
 
}

Output:

Before sorting:[Kevin, Brian, Steve, Bill, Obama]
List in ascending order:[Bill, Brian, Kevin, Obama, Steve]
List in descending orde :[Steve, Obama, Kevin, Brian, Bill]
List has preserved order :[Kevin, Brian, Steve, Bill, Obama]
New sorted list :[Bill, Brian, Kevin, Obama, Steve]

 

Sort objects that don’t implement Comparable

Now let us take a look at a scenario where you would like to sort a list of objects that you have created in your application. In the above example we sorted the list of names but now in the below example lets sort a list of Persons.

Example Class Person. Also take a not of the toString() method. I have implemented it so that I can format the output of the object.

package com.programtak.sort;
/**
 * A Person class with id, name and email 
 * 
 * @author programtak
 *
 */
public class Person {

 private String id;
 private String name;
 private String email;

 public Person(String id, String name, String email) {
  this.id = id;
  this.name = name;
  this.email = email;
 }

 public String getId() {
  return id;
 }

 public void setId(String id) {
  this.id = id;
 }

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

 public String getEmail() {
  return email;
 }

 public void setEmail(String email) {
  this.email = email;
 }

 @Override
 public String toString() {
  return "[id: " + this.id + ",name: " + this.name + ",email: " + this.email+"]"; 
 }
}


Now let us sort a list of Person objects based on name. We will do that using java.util.Comparator interface. In the below code I am creating an anonymous class from Comparator interface because I need it only as an input to the method. And inside the compare method I am comparing the persons on name. I have added null pointer checks so to show how the method implementation looks in real world. Here is the complete class:

package com.programtak.sort;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
 * This program sorts a list of Person in ascending and descending order.
 * 
 * @author programtak
 *
 */
public class SortPersonExample {


 public static void main(String[] args) {
  List<Person> personList = new ArrayList<Person>();
  personList.add(new Person("1", "Kevin", "kevin@email.com"));
  personList.add(new Person("2", "Brian", "brian@email.com"));
  personList.add(new Person("3", "Steve", "steve@email.com"));
  personList.add(new Person("4", null, "bill@email.com"));
  personList.add(new Person("5", "Obama", "obama@email.com"));
  
  
  SortPersonExample sortExample = new SortPersonExample();
  System.out.println("Before sorting:" + personList);
  sortExample.sortList(personList);
  System.out.println("After sorting:" + personList);
 }

 /**
  * This method sorts a list of persons based on name. If the name is null,
  * the object is propagated to the top
  * 
  * @param list
  *            - list to be sorted
  */
 private void sortList(List<Person> list) {
  Collections.sort(list, new Comparator<Person>() {
   public int compare(Person person1, Person person2) {
    // avoiding NullPointerException in case name is null 
    if (person1.getName() == null &amp;&amp; person2.getName() == null) {
     return 0;
    }
    if (person1.getName() == null) {
     return -1;
    }
    if (person2.getName() == null) {
     return 1;
    }
    return person1.getName().compareTo(person2.getName());
   }
  });
 }

}

Output :

Before sorting:[[id: 1,name: Kevin,email: kevin@email.com], [id: 2,name: Brian,email: brian@email.com], [id: 3,name: Steve,email: steve@email.com], [id: 4,name: null,email: bill@email.com], [id: 5,name: Obama,email: obama@email.com]]
After sorting:[[id: 4,name: null,email: bill@email.com], [id: 2,name: Brian,email: brian@email.com], [id: 1,name: Kevin,email: kevin@email.com], [id: 5,name: Obama,email: obama@email.com], [id: 3,name: Steve,email: steve@email.com]]

If you want to include code in your comments, you can do so by using this tag

<pre><code>
var foo = ‘bar’;
alert(‘foo’);
</code></pre>
Like this post? Don’t forget to share it!
  • Armagan

    It was so useful, thanks! but I have a question.
    Is there any special reason for you to override the sorting functions of Collection class? Or can we do like this?
    System.out.println(“Before sorting” + namesList);
    Collections.sort(namesList);
    System.out.println(“After ascending sorting” + namesList);
    Collections.reverse(namesList);
    System.out.println(“After descending sorting” + namesList);
    Thanks in advance!

    • Tak

      I am not overriding the collections.sort method. But I have taken it out into a method.’sortList’ so that it is clear that Collections.sort(List) only sorts lists of objects that implement Comparable.
      And yes you can do sorting as mentioned by you.
      I have just one comment to your code, Collections.reverse(List) will only reverse the list. It will not sort the list. See the code below



      System.out.println("Before sorting" + namesList);

      Collections.sort(namesList);

      System.out.println("After ascending sorting" + namesList);

      // only reverses the list, as the list is already sorted so it appears as though the list was sorted in reverse order
      //Collections.reverse(namesList);

      // In order to sort a list in descending order do as below
      Collections.sort(namesList, Collections.reverseOrder());

      System.out.println("After descending sorting" + namesList);

  • Armagan

    And also you said that “You will note that the this way of sort doesn’t generate a new List but sorts the same list. ” but I tried to make write reference of the list object before and after sorting with this function (Integer.toHexString(namesList.hashCode())) and I got different references! Where was I wrong? Does the same objects mean have the same reference numbers? Please help I am confused! :

    • Tak

      You are trying to use the hashCode() method to find the address of the list. And this is where you are wrong. The hashcode doesn’t guarantee to be the address of object in memory. Here is a good example that should help you understand it better..


      List<string> namesList = new ArrayList<>();
      namesList.add("Trumph");
      System.out.println("Before add hashcode: " +Integer.toHexString(namesList.hashCode()));
      namesList.add("Cruz");
      System.out.println("After add hashcode: " +Integer.toHexString(namesList.hashCode()));

      And the output of above code is :


      Before add hashcode: 95d4624d
      After add hashcode: 24d816c7

      In the above code you would see that the hashcode changes after adding an element to the list.

      The best way of finding out if two variables are pointing to same object would by using ‘==’


      System.out.println("Are objects equal:" + (list1 == list2));