Sorting an Arraylist of Objects Using a Custom Sorting Order

Sort ArrayList of custom Objects by property

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 java-8

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.

Sorting an ArrayList of objects using a custom sorting order

Here's a tutorial about ordering objects:

  • The Java Tutorials - Collections - Object Ordering

Although I will give some examples, I would recommend to read it anyway.


There are various way to sort an ArrayList. If you want to define a natural (default) ordering, then you need to let Contact implement Comparable. Assuming that you want to sort by default on name, then do (nullchecks omitted for simplicity):

public class Contact implements Comparable<Contact> {

private String name;
private String phone;
private Address address;

@Override
public int compareTo(Contact other) {
return name.compareTo(other.name);
}

// Add/generate getters/setters and other boilerplate.
}

so that you can just do

List<Contact> contacts = new ArrayList<Contact>();
// Fill it.

Collections.sort(contacts);

If you want to define an external controllable ordering (which overrides the natural ordering), then you need to create a Comparator:

List<Contact> contacts = new ArrayList<Contact>();
// Fill it.

// Now sort by address instead of name (default).
Collections.sort(contacts, new Comparator<Contact>() {
public int compare(Contact one, Contact other) {
return one.getAddress().compareTo(other.getAddress());
}
});

You can even define the Comparators in the Contact itself so that you can reuse them instead of recreating them everytime:

public class Contact {

private String name;
private String phone;
private Address address;

// ...

public static Comparator<Contact> COMPARE_BY_PHONE = new Comparator<Contact>() {
public int compare(Contact one, Contact other) {
return one.phone.compareTo(other.phone);
}
};

public static Comparator<Contact> COMPARE_BY_ADDRESS = new Comparator<Contact>() {
public int compare(Contact one, Contact other) {
return one.address.compareTo(other.address);
}
};

}

which can be used as follows:

List<Contact> contacts = new ArrayList<Contact>();
// Fill it.

// Sort by address.
Collections.sort(contacts, Contact.COMPARE_BY_ADDRESS);

// Sort later by phone.
Collections.sort(contacts, Contact.COMPARE_BY_PHONE);

And to cream the top off, you could consider to use a generic javabean comparator:

public class BeanComparator implements Comparator<Object> {

private String getter;

public BeanComparator(String field) {
this.getter = "get" + field.substring(0, 1).toUpperCase() + field.substring(1);
}

public int compare(Object o1, Object o2) {
try {
if (o1 != null && o2 != null) {
o1 = o1.getClass().getMethod(getter, new Class[0]).invoke(o1, new Object[0]);
o2 = o2.getClass().getMethod(getter, new Class[0]).invoke(o2, new Object[0]);
}
} catch (Exception e) {
// If this exception occurs, then it is usually a fault of the developer.
throw new RuntimeException("Cannot compare " + o1 + " with " + o2 + " on " + getter, e);
}

return (o1 == null) ? -1 : ((o2 == null) ? 1 : ((Comparable<Object>) o1).compareTo(o2));
}

}

which you can use as follows:

// Sort on "phone" field of the Contact bean.
Collections.sort(contacts, new BeanComparator("phone"));

(as you see in the code, possibly null fields are already covered to avoid NPE's during sort)

Sorting an arraylist of object base on its property in custom order

Unless you actually try to sort a list containing the items listed in the parameters of Ordering.explicit, it doesn't know how to sort them. It's also not clear if you've overridden your WeekSales.equals (and hashCode), which would be required for that to work too.

You need to actually tell it the fields to compare:

class YourComparator implements Comparator<WeekSales> {
private final Ordering<String> dayOrdering = Ordering.explicit(
"Monday", "Tuesday", ... );

@Override public int compare(WeekSales a, WeekSales b) {
return dayOrdering.compare(a.getDay(), b.getDay());
}
}

Sorting an ArrayList of Objects alphabetically

The sorting part can be done by implementing a custom Comparator<Vehicle>.

Collections.sort(vehiclearray, new Comparator<Vehicle>() {
public int compare(Vehicle v1, Vehicle v2) {
return v1.getEmail().compareTo(v2.getEmail());
}
});

This anonymous class will be used for sorting the Vehicle objects in the ArrayList on the base of their corresponding emails alphabetically.

Upgrading to Java8 will let you also implement this in a less verbose manner with a method reference:

Collections.sort(vehiclearray, Comparator.comparing(Vehicle::getEmail));


Related Topics



Leave a reply



Submit