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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30995101/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 10:29:12  来源:igfitidea点击:

Inline comparator vs custom comparator in Java

javaperformancecomparator

提问by Sarika.S

When sorting a list, is there any performance difference between using a java Comparator in-line (with an anonymous inner class) vs implementing a separate custom Comparator class?

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

1.

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.

2.

Collections.sort(list, new Comparator<WorkflowError>() {
    public int compare(WorkflowError obj1, WorkflowError obj2) {
        return obj1.getErrorCode().compareTo(obj2.getErrorCode());
    }
});

Also, when will the compare()method be invoked?

另外,什么时候会compare()调用该方法?

回答by Eran

There's shouldn't be any performance difference between the two variations, since anonymous classes should produce identical byte code as regular classes (assuming they have the same source code). The only difference is that they'll have a generated name.

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

The comparemethod will be invoked by Collections.sortwhenever it needs to compare two elements of the List to be sorted.

每当需要比较要排序的 List 的两个元素时,compare都会调用该方法Collections.sort

回答by Bohemian

There's also option 3 - a lambda Function:

还有选项 3 - 一个 lambda Function

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

which should be about 2 x faster, according to this benchmark data.

根据这个基准数据,这应该快大约 2 倍。

... or (thanks to @JB Nizet) option 4:

...或(感谢@JB Nizet)选项4:

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

回答by Paizo

I made a little test and found no difference (just in some small run the inline comparator shows a slightlybetter performace). This is the code used to make the test:

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

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

Comparator class:

比较器类:

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

and the output is:

输出是:

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

If you have several invocation to the comparator keeping an instance of it would be helpful

如果您对比较器进行多次调用并保留它的实例会有所帮助