How to sort Java collection on multiple columns

Java collection API, provide Comparator interface to sort the Java collection such as List. However, multi column sort is not possible. Multi column sort can be achieved using two Comparators in two different Collections.sort(Comparator...) calls. I am wonder why sort() method doesn't allow for varargs which is new in Java 5. Due to the limitation of sorting one column at once may giving performance problem (I don't know). Apache common has facility do multi column sorting.
package com.oj.ex;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;

import org.apache.commons.collections.comparators.ComparatorChain;

public class TestSorting {

 /**
  * @param args
  */
 @SuppressWarnings("unchecked")
 public static void main(String[] args) {
  List<Payment> payments = new ArrayList<Payment>();
  DateFormat df = new SimpleDateFormat("dd/MM/yyyy");
  try {
   payments.add(new Payment("200503",df.parse("21/03/2010"),"A"));
   payments.add(new Payment("200502",df.parse("10/02/2010"),"B"));
   payments.add(new Payment("200602",df.parse("22/03/2010"),"C"));
   payments.add(new Payment("200605",df.parse("22/02/2010"),"D"));
   payments.add(new Payment("200511",null,"E"));
   payments.add(new Payment("200511",null,"F"));
   payments.add(new Payment("200503",null,"G"));
  } catch (ParseException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  ComparatorChain chain = new ComparatorChain();
  
  chain.addComparator(new Comparator<Payment>(){

   @Override
   public int compare(Payment first, Payment second) {
    return first.getCalcid().compareTo(second.getCalcid());
   }},true);
  
  chain.addComparator(new Comparator<Payment>(){

   @Override
   public int compare(Payment first, Payment second) {
    if (first.getPaymentDate()==null && second.getPaymentDate()!=null) return 1;
    else if (first.getPaymentDate()!=null && second.getPaymentDate()==null) return -1;
    else if (first.getPaymentDate()==null && second.getPaymentDate()==null) return 0;
    else {
     if (first.getPaymentDate().before(second.getPaymentDate())) return -1;
     else if (first.getPaymentDate().after(second.getPaymentDate())) return 1;
    else return 0;
    }
   }},true);
  
  
  Collections.sort(payments, chain);
  for (Payment payment : payments) {
   System.out.println(payment.getName()+" | "+payment.getCalcid()+" | "+payment.getPaymentDate());
  }
  
 }

}

class Payment {
 private String calcid;
 private Date paymentDate;
 private String name;
 
 Payment(String calcid, Date paymentDate, String name){
  this.paymentDate = paymentDate;
  this.calcid = calcid;
  this.name = name;
 }
 public String getCalcid() {
  return calcid;
 }
 public void setCalcid(String calcid) {
  this.calcid = calcid;
 }
 public Date getPaymentDate() {
  return paymentDate;
 }
 public void setPaymentDate(Date paymentDate) {
  this.paymentDate = paymentDate;
 }
 public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 }
 
}
if you have any suggestion please comment.


Comments

Popular posts from this blog

How To: GitHub projects in Spring Tool Suite

Spring 3 Part 7: Spring with Databases

Parse the namespace based XML using Python