Built-in comparator versus custom comparator in Java

When sorting a list, is there a performance difference between using a Java comparator in a string (with an anonymous inner class) and 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 called?

+6
source share
3 answers

There is also option 3 - lambda Function :

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

which should be about 2 times faster, in accordance with these reference data .

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

 list.sort(Comparator.comparing(WorkflowError::getErrorCode)) 
+7
source

There should be no performance difference between the two options, since anonymous classes should create identical bytecode like regular classes (assuming they have the same source code). The only difference is that they will have a generated name.

The compare method will be called by Collections.sort when it needs to compare two elements of the list to be sorted.

+3
source

I did a little test and did not find a difference (only in a small run does the built-in comparator show slightly better performance). This is the code used to 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 output:

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

If you have several references to a comparator that supports an instance, this would be useful

+2
source

Source: https://habr.com/ru/post/989576/


All Articles