2015-06-23 8 views
6

Beim Sortieren einer Liste gibt es Leistungsunterschiede zwischen der Verwendung eines Java-Comparators inline (mit einer anonymen inneren Klasse) oder der Implementierung einer separaten benutzerdefinierten Vergleichsklasse?Inline-Vergleich zum benutzerdefinierten Vergleicher in Java

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()); 
    } 
}); 

Auch wenn wird die compare() Methode aufgerufen werden?

+0

Sie möchten vielleicht diese Antwort auschecken: http://StackOverflow.com/a/5468644/423991 –

+0

Da die Arbeit nach der gleichen Methode durchgeführt wird: Warum sollte es einen Unterschied geben? Und der Aufruf hängt vom Sortieralgorithmus ab - wann immer zwei Elemente in der Sammlung verglichen werden müssen. Und dann, zu einem gewissen Grad, der anfänglichen Reihenfolge der Daten. – laune

+0

"wenn diese Methode aufgerufen wird" - möchten Sie vielleicht über [Vergleichssortierung] (https://en.wikipedia.org/wiki/Comparison_sort) lesen. –

Antwort

3

Es sollte keinen Leistungsunterschied zwischen den beiden Varianten geben, da anonyme Klassen identische Byte-Codes wie reguläre Klassen erzeugen sollten (vorausgesetzt, sie haben denselben Quellcode). Der einzige Unterschied ist, dass sie einen generierten Namen haben.

Die Methode compare wird von aufgerufen, wenn zwei Elemente der zu sortierenden Liste miteinander verglichen werden müssen.

+2

Für eine * Antwort * ohne "sollte nicht" und "sollte" hätten Sie vielleicht eine Byte-Code-Analyse erstellt ;-)) – laune

+0

@laune Das ist ein guter Punkt. Ich entschuldige mich dafür, jetzt keine Zeit dafür zu haben. – Eran

7

Es gibt auch die Option 3 - eine Lambda Function:

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

die schneller über 2 x sein sollte, nach this benchmark data.

... oder (dank @JB Nizet) Option 4:

list.sort(Comparator.comparing(WorkflowError::getErrorCode)) 
+4

Wenn Sie lambdas verwenden, dann sind Sie auf Java 8. Und wenn Sie auf Java 8 sind, können Sie einfach 'list.sort (Comparator.comparing (WorkflowError :: getErrorCode)' –

+1

Warum Lambda sollte schneller sein ? Der Post, den Sie verknüpft haben, gibt an, dass es hier keinen Leistungsunterschied zwischen anonymer Klasse und Lambda gibt. – apangin

2

machte ich einen kleinen Test und fand keinen Unterschied (nur in einigen kleinen Lauf der Inline-Komparator zeigt eine leicht besser Performace). Dies ist der Code verwendet, um den Test zu machen:

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; 
    } 
} 

Vergleicher Klasse:

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

und der Ausgang ist:

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

Wenn Sie mehr Aufruf an den Komparator haben hält eine Instanz es wäre hilfreich

Verwandte Themen