[SalesForce] Apex equivalent of Java Comparator

I already know about the equivalent of Comparable – the class to be sorted should implement Comparable and then you can sort a List of said class.

But, how about Comparator?

In java, the Collections.sort() method can take a Comparator, so that the sorting and the class implementation are separated. This enables a class to be sorted in different ways.

If I want more than one way of sorting a class, how can this be done in Apex? I have found nothing similar. I've tried extending the class and over-riding the compareTo() method, but that introduced many problems. Is there a better way?

Best Answer

While Comparator isn't available out of the box, it's not terribly hard to implement. However, your performance will be considerably worse than a native solution, so you'll need to test and see how many rows you can actually sort before it becomes intolerable.

public abstract class Comparator {
    public abstract Integer compare(Object o1, Object o2);
    public static void sort(Object[] values, Comparator comp) {
        //  Obtain the list type of values
        Object[] temp = values.clone();
        temp.clear();
        //  Helper class for sorting using Comparable
        Helper[] tempValues = new Helper[0];
        for(Object value: values) {
            tempValues.add(new Helper(comp, value));
        }
        //  Perform sort
        tempValues.sort();
        //  Extract values back into temp list
        for(Helper helper: tempValues) {
            temp.add(helper.value);
        }
        //  And set the list to the new, sorted order
        values.clear();
        values.addAll(temp);
    }
    //  Simply calls Comparator when asked.
    class Helper implements Comparable {
        Comparator method;
        Object value;
        Helper(Comparator comp, Object val) {
            method = comp;
            value = val;
        }
        public Integer compareTo(Object o) {
            return method.compare(value, ((Helper)o).value);
        }
    }
}

From here, you can create your own solutions:

public class AccountNameComparator extends Comparator {
    public override Integer compare(Object a, Object b) {
        return ((Account)a).name.compareTo(((Account)b).name);
    }
}

Which would let you sort as you like:

Account[] accounts = [SELECT Name FROM Account ORDER BY CreatedDate LIMIT 5];
Comparator.sort(accounts, new AccountNameComparator());

This should work with any sort of data type, even custom classes, as long as you can implement the "compare" method. This version also doesn't take into consideration null values specifically, so you may need to adjust your implementations accordingly.

Related Topic