Sort ArrayList of custom Objects by property

2018-12-30 22:34发布

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);
    ...
}

25条回答
初与友歌
2楼-- · 2018-12-30 22:50

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.

查看更多
查无此人
3楼-- · 2018-12-30 22:52

Using Java 8 use can define the Comparator in one line using Comparator.comparing()

Use any of the following way:

Option 1:

listToBeSorted.sort(Comparator.comparing(CustomObject::getStartDate));

Option 2:

Collections.sort(listToBeSorted, Comparator.comparing(CustomObject::getStartDate));
查看更多
几人难应
4楼-- · 2018-12-30 22:56

your customComparator class must implement java.util.Comparator in order to be used. it must also overide compare() AND equals()

compare() must answer the question: Is object 1 less than, equal to or greater than object 2?

full docs: http://java.sun.com/j2se/1.5.0/docs/api/java/util/Comparator.html

查看更多
呛了眼睛熬了心
5楼-- · 2018-12-30 22:57

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) {
        ...
    }
});
查看更多
牵手、夕阳
6楼-- · 2018-12-30 22:58

Function & method reference

The Collections.sort method can sort a List using a Comparator you pass. That Comparator can be implemented using the Comparator.comparing method where you can pass a method reference as the necessary Function. Fortunately, the actual code is much simpler and shorter than this description.

For Java 8:

Collections.sort(list, comparing(ClassName::getName));

or

Collections.sort(list, comparing(ClassName::getName).reversed());

Another way is

Collections.sort(list, comparing(ClassName::getName, Comparator.nullsLast(Comparator.naturalOrder())));
查看更多
梦寄多情
7楼-- · 2018-12-30 22:59

From Java 8 and onward we don't have to use Collections.sort() directly. List interface has a default sort() method:

List<User> users = Arrays.asList(user1,user2,user3);
users.sort( (u1, u2) -> { 
return u1.getFirstName.compareTo(u2.getFirstName());}); 

See http://visvv.blogspot.in/2016/01/sorting-objects-in-java-8.html.

查看更多
登录 后发表回答