【问题标题】:Performance of thenComparing vs thenComparingInt - which to use?thenComparing 与 thenComparingInt 的性能 - 使用哪个?
【发布时间】:2014-06-27 12:47:21
【问题描述】:

我有一个问题,如果我在比较整数,那么调用 thenComparingInt(My::intMethod) 与 thenComparing(My::intMethod) 是否存在性能差异,换句话说,如果我在比较不同的类型,参考和原始,例如String, int 等。我的一部分只是想说 compare().thenComparing().thenComparing() 等,但如果第三次调用比较 int 或 Integer 值,我应该做 compare.thenComparing().thenComparingInt() ?

我假设 compare() 和 thenComparing() 使用 compareTo 方法来比较幕后的任何给定类型,或者可能是整数,Integer.compare?我还假设我最初问题的答案可能涉及性能,因为 thenComparingInt 会知道正在传入一个 int,而 thenComparing 必须将 int 自动装箱为 Integer,然后可能转换为 Object?

另外,我想到另一个问题 - 是否有链接方法引用的方法,例如Song::getArtist::length getArtist 在哪里返回一个字符串?原因是我想做这样的事情:

songlist.sort(
            Comparator.comparing((Song s) -> s.getArtist().length()));


    songlist.sort(
            Comparator.comparing(Song::getArtist, 
                    Comparator.comparingInt(String::length)));


    songlist.sort(
            Comparator.comparing(Song::getArtist, String::length));

在 3 个示例中,前两个编译但底部似乎在 Eclipse 中引发编译错误,我会认为 String::length 的第二个参数是有效的?但也许不是因为它期望 Comparator 而不是函数?

【问题讨论】:

    标签: sorting java-8 comparator


    【解决方案1】:

    问题 1

    我认为thenComparingInt(My::intMethod) 可能会更好,因为它应该避免装箱,但您必须同时尝试这两个版本,看看它是否真的有所作为。

    问题 2

    songlist.sort(
            Comparator.comparing(Song::getArtist, String::length));
    

    无效,因为第二个参数应该是 Comparator 而不是返回 int 的方法。

    【讨论】:

    • 我的猜测是,原始专业化只会获得很少的性能。转义分析检测到自动装箱 int 被限制在比较方法的范围内不会有太大问题,然后可以内联 Integer.compareTo 方法以产生与没有自动装箱几乎相同的结果。因此,必须进行基准测试才能找到实际差异。
    • @MarkoTopolnik 要是这样就好了。在我们承诺包含原始流专业化之前,已经进行了大量实际测量。也就是说,性能很少是最重要的要求。如果您的集合中有六个元素,那么无论您进行多少拳击,排序都可能足够快,并且足够快也足够快。
    • @BrianGoetz 事实上,当使用整数缓存范围之外的整数时,我已经将Arrays.sort(integerArray, comparing(Integer::intValue));Arrays.sort(integerArray, comparingInt(Integer::intValue)); 进行了比较,性能比为3.5:1,有利于原始专业化;当在缓存范围内 (0..127) 时,盒装变体的性能更好(2 比 1)。这表明 Escape Analysis 不允许堆栈分配,基于我之前的观察,即 EA 的整数比从缓存中查找时的性能更好
    • @BrianGoetz ...根据上述发现,我还测试了Arrays.sort(integerArray, comparing(i->new Integer(i.intValue())));---并且,你瞧,在这种情况下,比率仅为 1.5 比 1。由于涉及缓存查找的代码路径,我忽略了 Integer.valueOf(换句话说,自动装箱代码)不能被 EA 处理。所以我的预测毕竟成立:在 E​​A 生效后,差异变得非常小。
    • @MarkoTopolnik 我同意 Brian Goetz 的说法,因为他是 Java 8 的作者之一。
    猜你喜欢
    • 2010-11-11
    • 2012-10-02
    • 1970-01-01
    • 2012-06-11
    • 2014-12-19
    • 2016-03-07
    • 2021-04-25
    • 2015-01-09
    • 2012-08-31
    相关资源
    最近更新 更多