Categories
comparator date java sorting

Sort ArrayList of custom Objects by property

1253

I read about sorting ArrayLists using a Comparator but in all of the examples people used compareTo which according to some research is a method for Strings.

I wanted to sort an ArrayList of custom objects by one of their properties: a Date object
(getStartDay()). Normally I compare them by item1.getStartDate().before(item2.getStartDate()) so I was wondering whether I could write something like:

public class CustomComparator {
    public boolean compare(Object object1, Object object2) {
        return object1.getStartDate().before(object2.getStartDate());
    }
}

public class RandomName {
    ...
    Collections.sort(Database.arrayList, new CustomComparator);
    ...
}

2

1684

Since Date implements Comparable, it has a compareTo method just like String does.

So your custom Comparator could look like this:

public class CustomComparator implements Comparator<MyObject> {
    @Override
    public int compare(MyObject o1, MyObject o2) {
        return o1.getStartDate().compareTo(o2.getStartDate());
    }
}

The compare() method must return an int, so you couldn’t directly return a boolean like you were planning to anyway.

Your sorting code would be just about like you wrote:

Collections.sort(Database.arrayList, new CustomComparator());

A slightly shorter way to write all this, if you don’t need to reuse your comparator, is to write it as an inline anonymous class:

Collections.sort(Database.arrayList, new Comparator<MyObject>() {
    @Override
    public int compare(MyObject o1, MyObject o2) {
        return o1.getStartDate().compareTo(o2.getStartDate());
    }
});

Since

You can now write the last example in a shorter form by using a lambda expression for the Comparator:

Collections.sort(Database.arrayList, 
                        (o1, o2) -> o1.getStartDate().compareTo(o2.getStartDate()));

And List has a sort(Comparator) method, so you can shorten this even further:

Database.arrayList.sort((o1, o2) -> o1.getStartDate().compareTo(o2.getStartDate()));

This is such a common idiom that there’s a built-in method to generate a Comparator for a class with a Comparable key:

Database.arrayList.sort(Comparator.comparing(MyObject::getStartDate));

All of these are equivalent forms.

15

  • 39

    +1 for mentioning that it should return int and that you’d better to use Date#compareTo() for this. Why this isn’t upvoted above the other answer is beyond me. This link may also be useful: Object Ordering Tutorial at Sun.com.

    – BalusC

    May 6, 2010 at 21:26


  • 7

    I think the answer best should also include the proper way to do it in Java 8. Collections.sort(list, Comparator.comparing(MyObject::getStartDate)); which reads better and is less error prone. It’s very easy to write return o1.getStartDate().compareTo(o1.getStartDate());

    – Kuba

    May 16, 2014 at 14:00

  • 2

    Comparator class should be static 🙂

    Jun 27, 2014 at 9:14

  • 4

    @Kuba better yet, use List.sort().

    – shmosel

    Apr 25, 2016 at 18:31

  • 3

    This solution does not work on Android API <24. Do you guys know a solution for this?

    Mar 15, 2018 at 16:37

198

Classes that has a natural sort order (a class Number, as an example) should implement the Comparable interface, whilst classes that has no natural sort order (a class Chair, as an example) should be provided with a Comparator (or an anonymous Comparator class).

Two examples:

public class Number implements Comparable<Number> {
    private int value;

    public Number(int value) { this.value = value; }
    public int compareTo(Number anotherInstance) {
        return this.value - anotherInstance.value;
    }
}

public class Chair {
    private int weight;
    private int height;

    public Chair(int weight, int height) {
        this.weight = weight;
        this.height = height;
    }
    /* Omitting getters and setters */
}
class ChairWeightComparator implements Comparator<Chair> {
    public int compare(Chair chair1, Chair chair2) {
        return chair1.getWeight() - chair2.getWeight();
    }
}
class ChairHeightComparator implements Comparator<Chair> {
    public int compare(Chair chair1, Chair chair2) {
        return chair1.getHeight() - chair2.getHeight();
    }
}

Usage:

List<Number> numbers = new ArrayList<Number>();
...
Collections.sort(numbers);

List<Chair> chairs = new ArrayList<Chair>();
// Sort by weight:
Collections.sort(chairs, new ChairWeightComparator());
// Sort by height:
Collections.sort(chairs, new ChairHeightComparator());

// You can also create anonymous comparators;
// Sort by color:
Collections.sort(chairs, new Comparator<Chair>() {
    public int compare(Chair chair1, Chair chair2) {
        ...
    }
});

5

  • I tried that – but when I want to access the comparator class ChairWeightComparator outside in any other class I do not get access to this class (of course not since its not public). Do I need to create a new public ChairWeightComparator class in a separate file? – am I really the first one to try this after 3 years or did I miss sth?

    Mar 23, 2014 at 9:01


  • @user387184 – simply make it public, and put it in it’s own file (preferably it’s own package as well) and you’ll be able to use it everywhere in you project. No need to create an additional class!

    – Björn

    Mar 23, 2014 at 17:36

  • you mean create a new file – not a class and put in the code: “class ChairWeightComparator implements Comparator<Chair> {….” ?

    Mar 23, 2014 at 18:28

  • @user387184, exactly – but with the key word public in front of class.

    – Björn

    Mar 24, 2014 at 6:00

  • This is not working on my Laptop. It shows int cannot be dereferenced error. How to correct it ?

    – Alex

    Oct 17, 2020 at 4:03

162

For sorting an ArrayList you could use the following code snippet:

Collections.sort(studList, new Comparator<Student>(){
    public int compare(Student s1, Student s2) {
        return s1.getFirstName().compareToIgnoreCase(s2.getFirstName());
    }
});

3

  • 1

    Anybody using lambda stackoverflow.com/questions/2784514/…

    – Sorter

    Sep 5, 2014 at 13:13

  • That sorts but gives double value for each element

    – Samir

    Sep 23, 2016 at 17:41

  • This is not working on my Laptop. It shows int cannot be dereferenced error. How to correct it ?

    – Alex

    Oct 17, 2020 at 4:03