Java中的内联比较器与自定义比较器

时间:2015-06-23 06:11:01

标签: java performance comparator

对列表进行排序时,在线使用java Comparator(使用匿名内部类)与实现单独的自定义Comparator类之间是否有任何性能差异?

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 个答案:

答案 0 :(得分:13)

还有选项3 - lambda Function

Collections.sort(list, (a, b) -> a.getErrorCode().compareTo(b.getErrorCode()));
根据{{​​3}},

应该快2倍左右。

...或(感谢this benchmark data)选项4:

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

答案 1 :(得分:3)

两种变体之间不应存在任何性能差异,因为匿名类应该生成与常规类相同的字节代码(假设它们具有相同的源代码)。唯一的区别是他们会生成一个名字。

只要需要比较要排序的List的两个元素,compare方法就会调用Collections.sort方法。

答案 2 :(得分:3)

我做了一点测试,发现没有区别(只是在一些小的运行中,内联比较器显示略微更好的性能)。这是用于进行测试的代码:

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

如果你有多次调用比较器,保持它的实例会有帮助