Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inline comparator vs custom comparator in Java

When sorting a list, is there any performance difference between using a java Comparator in-line (with an anonymous inner class) vs implementing a separate custom Comparator class?

1.

public class SortByErrorComparator implements Comparator<WorkflowError> {
    public int compare(WorkflowError obj1, WorkflowError obj2) {
        return obj1.getErrorCode().compareTo(obj2.getErrorCode());
    }
}
Collections.sort(list, new SortByErrorComparator()) ;

2.

Collections.sort(list, new Comparator<WorkflowError>() {
    public int compare(WorkflowError obj1, WorkflowError obj2) {
        return obj1.getErrorCode().compareTo(obj2.getErrorCode());
    }
});

Also, when will the compare() method be invoked?

like image 493
Sarika.S Avatar asked Jun 23 '15 06:06

Sarika.S


People also ask

What is difference between Comparator and comparable in Java?

Comparable in Java is an object to compare itself with another object, whereas Comparator is an object for comparing different objects of different classes. Comparable provides the compareTo() method to sort elements in Java, whereas Comparator provides compare() method to sort elements in Java.

What is comparable and Comparator?

1) Comparable provides a single sorting sequence. In other words, we can sort the collection on the basis of a single element such as id, name, and price. The Comparator provides multiple sorting sequences. In other words, we can sort the collection on the basis of multiple elements such as id, name, and price etc.

Can we use compareTo in Comparator?

Comparator detaches the sorting logic from your object and contains the compareTo() logic within your sort() method.

How does Compare method of Comparator work in Java?

The compare() method accepts two objects as input parameters and returns an integer value. int compare(T o1, T o2); Comparator decides the sorting order based on the integer value returned from the compare() method. 0, if values in o1 and o2 are equal.


2 Answers

There's also option 3 - a lambda Function:

Collections.sort(list, (a, b) -> a.getErrorCode().compareTo(b.getErrorCode()));

which should be about 2 x faster, according to this benchmark data.

... or (thanks to @JB Nizet) option 4:

list.sort(Comparator.comparing(WorkflowError::getErrorCode))
like image 174
Bohemian Avatar answered Sep 24 '22 19:09

Bohemian


I made a little test and found no difference (just in some small run the inline comparator shows a slightly better performace). This is the code used to make the test:

public class ComparatorTest {

    private static final int MAX = 1000000;
    private static final int RUN = 10000;

    public static void main(String[] args) {

        List<A> list = new ArrayList<A>();

        long externalComparatorClassTotalTime = 0;
        long inlineCompartorTotalTime = 0;

        for (int i = RUN; i > 0; i--) {
            init(list);
            externalComparatorClassTotalTime += externalComparatorClassTest(list);
            init(list);
            inlineCompartorTotalTime += inlineCompartorTest(list);
        }

        System.out.format("List with %d elements and %d runs%n", MAX, RUN);
        System.out.println("external Comparator class average millis: " + externalComparatorClassTotalTime / RUN);
        System.out.println("inline Comparator class average millis: " + inlineCompartorTotalTime / RUN);
    }

    private static void init(List<A> list) {
        list.clear();
        for (int i = MAX; i > 0; i--) {
            list.add(new A(i));
        }
    }

    private static long inlineCompartorTest(List<A> secondList) {
        long start = System.currentTimeMillis();

        Collections.sort(secondList, new Comparator<A>() {
                public int compare(A obj1, A obj2) {
                    return obj1.getVal().compareTo(obj2.getVal());
                }
        });

        return System.currentTimeMillis() - start;
    }

    private static long externalComparatorClassTest(List<A> firstList) {
        long start = System.currentTimeMillis();

        Collections.sort(firstList, new MyComparatorOne());

        return System.currentTimeMillis() - start;
    }
}

Comparator class:

public class MyComparatorOne implements Comparator<A> {
    public int compare(A obj1, A obj2) {
        return obj1.getVal().compareTo(obj2.getVal());
    }
}

and the output is:

List with 1000000 elements and 10000 runs
external Comparator class average millis: 3
inline Comparator class average millis: 3

If you have several invocation to the comparator keeping an instance of it would be helpful

like image 24
Paizo Avatar answered Sep 25 '22 19:09

Paizo