リストを並べ替える場合、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()
メソッドはいつ呼び出されますか?
オプション3もあります-ラムダFunction
:
Collections.sort(list, (a, b) -> a.getErrorCode().compareTo(b.getErrorCode()));
このベンチマークデータ によると、これは約2倍高速になるはずです。
...または( @ JB Nizet に感謝)オプション4:
list.sort(Comparator.comparing(WorkflowError::getErrorCode))
私は少しテストを行い、違いはありませんでした(いくつかの小さな実行で、インラインコンパレーターはわずかにより良いパフォーマンスを示しています)。これはテストを行うために使用されるコードです:
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
あなたがそれのインスタンスを維持するコンパレータへの複数の呼び出しがある場合、それは役に立ちます
匿名クラスは通常のクラスと同じバイトコードを生成する必要があるため(これらのバリエーションは同じソースコードであると想定)、2つのバリエーションの間にパフォーマンスの違いはありません。唯一の違いは、名前が生成されることです。
compare
メソッドは、並べ替えるリストの2つの要素を比較する必要があるときに、Collections.sort
によって呼び出されます。