17

I have an ArrayList of object. The object contain attributes date and value. So I want to sort the objects on the date, and for all objects in the same date I want to sort them on value. How can I do that?

Thang Pham
  • 38,125
  • 75
  • 201
  • 285

5 Answers5

23

Implement a custom Comparator, then use Collections.sort(List, Comparator). It will probably look something like this:

public class FooComparator implements Comparator<Foo> {
    public int compare(Foo a, Foo b) {
        int dateComparison = a.date.compareTo(b.date);
        return dateComparison == 0 ? a.value.compareTo(b.value) : dateComparison;
    }
}

Collections.sort(foos, new FooComparator());
harto
  • 89,823
  • 9
  • 47
  • 61
3
public static <T> void sort(List<T> list, final List<Comparator<T>> comparatorList) {  
       if (comparatorList.isEmpty()) {//Always equals, if no Comparator.  
            throw new IllegalArgumentException("comparatorList is empty.");  
       }  
       Comparator<T> comparator = new Comparator<T>() {  
       public int compare(T o1, T o2) {  
               for (Comparator<T> c:comparatorList) {  
                   if (c.compare(o1, o2) > 0) {  
                     return 1;  
                   } else if (c.compare(o1, o2) < 0) {  
                     return -1;  
                   }  
               }  
               return 0;  
         }  
       };  
       Collections.sort(list, comparator);  
  } 
卢声远 Shengyuan Lu
  • 31,208
  • 22
  • 85
  • 130
  • Consider using a library call to merge the comparators instead of implementing your own here--see Guava's `Ordering` class: http://guava-libraries.googlecode.com/svn/trunk/javadoc/com/google/common/collect/Ordering.html – Michael Brewer-Davis Nov 30 '10 at 04:40
2

Java-8 solution using Stream API:

List<Foo> sorted = list.stream()
                        .sorted(Comparator.comparing(Foo::getDate)
                                        .thenComparing(Foo::getValue))
                        .collect(Collectors.toList());

If you want to sort the original list itself:

list.sort(Comparator.comparing(Foo::getDate)
                    .thenComparing(Foo::getValue)); 
Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110
1

If you want sample code looks like, you can use following:

Collections.sort(foos, new Comparator<Foo>{
    public int compare(Foo a, Foo b) {
        int dateComparison = a.date.compareTo(b.date);
        return dateComparison == 0 ? a.value.compareTo(b.value) : dateComparison;
    }
});
Tony
  • 11
  • 2
0

If the class of the object implements Comparable, then all you need to do is properly code the compareTo method to first compare dates, and then if dates are equal, compare values, and then return the appropriate int result based on the findings.

Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
  • Or you can do this with a Comparator as noted above if you don't want to make the class implement Comparable.... your choice. If you use a Comparator, then the compare method will utilize my suggestion above. – Hovercraft Full Of Eels Nov 30 '10 at 02:33