2015-06-23 2 views
6

При сортировке списка существует ли разница в производительности между использованием Java-компаратора в строке (с анонимным внутренним классом) и внедрением отдельного пользовательского класса Comparator?Встроенный компаратор в сравнении с обычным компаратором в 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()); 
    } 
}); 

Кроме того, когда будет метод compare() быть вызван?

+0

Возможно, вы захотите проверить этот ответ: http://stackoverflow.com/a/5468644/423991 –

+0

Поскольку работа выполняется по тому же методу: почему должна быть разница? И вызов зависит от алгоритма сортировки - всякий раз, когда нужно сравнивать два элемента в коллекции. И, в некоторой степени, от первоначального упорядочения данных. – laune

+0

«когда этот метод будет вызываться» - вы можете прочитать о [сортировке сортировки] (https://en.wikipedia.org/wiki/Comparison_sort). –

ответ

3

Не должно быть разницы в производительности между этими двумя вариантами, поскольку анонимные классы должны создавать идентичный байт-код в качестве обычных классов (при условии, что они имеют одинаковый исходный код). Единственное различие заключается в том, что у них будет сгенерированное имя.

Метод compare будет вызываться Collections.sort всякий раз, когда ему нужно сравнить два элемента списка, которые нужно отсортировать.

+2

Для * ответа * без «should not» и «should» вы могли бы произвести анализ байтового кода ;-)) – laune

+0

@laune Это хороший момент. Прошу прощения за то, что у меня нет времени на это. – Eran

7

Там также вариант 3 - лямбда Function:

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

, который должен быть около 2 х быстрее, по this benchmark data.

... или вариант 4 (спасибо @JB Nizet):

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

Если вы используете lambdas, то вы на Java 8. И если вы на Java 8, вы можете просто использовать 'list.sort (Comparator.comparing (WorkflowError :: getErrorCode)' –

+1

Почему лямбда должна быть быстрее ? Сообщение, которое вы связали, говорит, что различия между анонимным классом и лямбдой отсутствуют. – apangin

2

Я сделал небольшой тест и не нашел никакой разницы (только в некоторой малой перспективе рядного компаратор показывает слегка лучше Performace). Это код, который используется, чтобы сделать тест:

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

Компаратора класс:

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

и выход:

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

Если у вас есть несколько призывания к компаратору, сохраняя экземпляр из этого было бы полезно

Смежные вопросы