6

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?

  • 1
    Oh now I hate Apex. I long to return to Java one day. – NickJ Oct 13 '15 at 17:04
  • 1
    Watch this question as sfdcfox may bring you back from the edge..... – Eric Oct 13 '15 at 20:01
11

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.

  • 2
    This is a clever solution! It's a shame that so much time and effort has to go into getting round Apex's many shortcomings, however. – NickJ Oct 14 '15 at 9:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.