Sort A List of Objects

As a Java programmer, I often need to sort a list of objects. If the object is a primitive type, such as String, Integer, Long, Float, Double, or Date, it is easy to use Collections.sort(). However, it is not easy to sort a list of user defined objects, which do not implement the Comparable interface, for example, a Person object, as defined below. If you want to sort a list of Person objects by id in ascending order, you hav to provide a Comparator class to encapsulate the ordering. One possible comparator class is defined below.

Instead, a generic comparator class is defined in this post to sort lists of primitive as well as user defined objects, in any specified order and by any specified field(s).

public class Person {
    //fields
    private int id;
    private String name;
    private Payment pay;
    //constructor
    public Person(String name, int id,
                   int startSal, int startBon){
        this.name = name;
        this.id = id;
        this.pay = new Payment(startSal, startBon);
    }
    //method get name
    public String getName(){
        return name;
    }
    //method get id
    public int getId(){
        return id;
    }
    //method get start salary
    public int getStartSalary(){
        return pay.startSalary;
    }
    //method get start bonus
    public int getStartBonus(){
       return pay.startBonus;
    }
    //inner payment class
    private class Payment{
       int startSalary;
       int startBonus;
       public Payment(int sal, int bon){
          this.startSalary = sal;
          this.startBonus = bon;
       }
    }
}

One possible Comparator class with above aim might be:

import java.util.Comparator;

public class SortPersonById implements Comparator<Person> {
	@Override
	public int compare(Person p1, Person p2) {
		if(p1.getId() > p2.getId()){
			return 1;
		} else if (p1.getId() < p2.getId()){
			return -1;
		} else {
			return 0;
		}
	}
}

Then one can use

Collections.sort(personList, new SortPersonById()); 

to sort the list personList by id in ascending order.

Generic Comparator

What if the user wants to sort the personList by name instead of id, or in descending instead of ascending order, or by id first and then name second? It is tedious to write one class for each of these situations. I have built a GenericComparator class to handle these situaitons. The reflection technology is used for accessing fields in the class. This generic class can be used to sort lists of primitive as well as user defined objects.

There are two constructors shown below. Constructor 1 defines default ascending order and the sort field names. The varargs format of sort field names is used for multiple fields and multiple level of fields. Take the Person class above for example, the user can define multiple fields names such as id, name, and pay.StartSalary or pay.startBonus. Constructor 2 works in the same way, excepts the user can defined sorting order.

Constructor 1

public GenericComparator(String... sortFieldNames) {
		this.bAscendingOrder = true;
		//read sort filed names into 
		for(String fieldName: sortFieldNames){
			System.out.println(fieldName);
			List<String> tempList = new ArrayList<String>();
			for(String name : fieldName.split("\\.")){
				System.out.println(name);
				tempList.add(name);
			}
			this.alFieldNameMatrix.add(tempList);
		}
	}

Constructor 2

public GenericComparator(final boolean sortAscending, String... sortFieldNames) {
		this.bAscendingOrder = sortAscending;
		//read sort filed names into 
		for(String fieldName: sortFieldNames){
			List<String> tempList = new ArrayList<String>();
			for(String name : fieldName.split("\\.")){
				tempList.add(name);
			}
			this.alFieldNameMatrix.add(tempList);
		}
	}

How to Use

An example is posted here to illustrate how to use the GenericComparator class.


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

public class TestGenericComparator {
	
	public static void main(String[] args) {

		// Build a list of persons with different names and ids
		List<Person> personList = new ArrayList<Person>();
		personList.add(new Person("Angela", 102, 50000, 4500));
		personList.add(new Person("Mike",101, 65000, 5500));
		personList.add(new Person("Lisa", 104, 75000,4500));
		personList.add(new Person("Bob", 103, 50000, 4500));
		
		//sort personList by name field 
		printInfo("sort personList by name field: ");
		Collections.sort(personList, new GenericComparator("name"));
		printPersonList(personList);
		
		//sort personList by id field in ascending order
		printInfo("sort personList by id field in ascending order:");
		Collections.sort(personList, new GenericComparator(true,"id"));
		printPersonList(personList);
		
		//sort personList by id field in descending order
		printInfo("sort personList by id field in descending order:");
		Collections.sort(personList, new GenericComparator(false,"id"));
		printPersonList(personList);
		
		//sort personList by pay field's start salary
		printInfo("sort personList by pay field's start salary:");
		Collections.sort(personList, new GenericComparator("pay.startSalary"));
		printPersonList(personList);
		
		//sort personList by pay field's start salary first, and then by id
		printInfo("sort personList by pay field's start salary and id");
		Collections.sort(personList, new GenericComparator("pay.startSalary", "id"));
		printPersonList(personList);
		
	}

	/**
	 * @param personList
	 */
	private static void printPersonList(List<Person> personList) {
		for(Person p: personList){
			System.out.println(p.getName() + "\t" + p.getId() + "\t" + p.getStartSalary() + "\t" +p.getStartBonus());
		}
		System.out.println("-------------");
	}
	private static void printInfo(String info){
		System.out.println(info);
	}

}

Execution results:

sort personList by name field: 
Angela	102	50000	4500
Bob	103	50000	4500
Lisa	104	75000	4500
Mike	101	65000	5500
-------------
sort personList by id field in ascending order:
Mike	101	65000	5500
Angela	102	50000	4500
Bob	103	50000	4500
Lisa	104	75000	4500
-------------
sort personList by id field in descending order:
Lisa	104	75000	4500
Bob	103	50000	4500
Angela	102	50000	4500
Mike	101	65000	5500
-------------
sort personList by pay field's start salary:
Bob	103	50000	4500
Angela	102	50000	4500
Mike	101	65000	5500
Lisa	104	75000	4500
-------------
sort personList by pay field's start salary and then by id: 
Angela	102	50000	4500
Bob	103	50000	4500
Mike	101	65000	5500
Lisa	104	75000	4500
-------------

Detailed source code and implement examples are available through my GitHub. Please feel free to leave your comments.

Reference

  1. Making a Generic Comparator Class

  2. Generic Comparator in Java