web-dev-qa-db-ja.com

Javaのインラインコンパレータとカスタムコンパレータ

リストを並べ替える場合、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()メソッドはいつ呼び出されますか?

10
Sarika.S

オプション3もあります-ラムダFunction

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

このベンチマークデータ によると、これは約2倍高速になるはずです。

...または( @ JB Nizet に感謝)オプション4:

list.sort(Comparator.comparing(WorkflowError::getErrorCode))
13
Bohemian

私は少しテストを行い、違いはありませんでした(いくつかの小さな実行で、インラインコンパレーターはわずかにより良いパフォーマンスを示しています)。これはテストを行うために使用されるコードです:

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

あなたがそれのインスタンスを維持するコンパレータへの複数の呼び出しがある場合、それは役に立ちます

3
Paizo

匿名クラスは通常のクラスと同じバイトコードを生成する必要があるため(これらのバリエーションは同じソースコードであると想定)、2つのバリエーションの間にパフォーマンスの違いはありません。唯一の違いは、名前が生成されることです。

compareメソッドは、並べ替えるリストの2つの要素を比較する必要があるときに、Collections.sortによって呼び出されます。

3
Eran