【问题标题】:Replaced a custom Comparator with Comparator.comparing() - why does this work?用 Comparator.comparing() 替换了自定义 Comparator - 为什么会这样?
【发布时间】:2017-01-05 03:34:13
【问题描述】:

我有一个List<Meeting>,会议如下:

public class Meeting {
    private Calendar date;
    public Calendar getDate() {
      return this.date
    }
}

最初在流的 .sorted() 部分有一个自定义 lambda 比较器(myMeetingListList<Meeting>):

return myMeetingList.parallelStream()
                    .filter(m -> m.getContacts().contains(contact))
                    .sorted((m1,m2) -> m1.getDate().compareTo(m2.getDate()))
                    .collect(Collectors.toList());

我偶然发现了一些东西。我认为它有效,但我不知道为什么。我没有创建自定义比较器,而是将其替换为看起来像静态方法引用的东西:

return myMeetingList.parallelStream()
                    .filter(m -> m.getContacts().contains(contact))
                    .sorted(Comparator.comparing(Meeting::getDate))
                    .collect(Collectors.toList());

我相信它有效,但老实说我不知道​​为什么。 Comparator.comparing() 的实现之一的 JavaDoc 显示

static <T,U extends Comparable<? super U>> Comparator<T> comparing(Function<? super T,? extends U> keyExtractor)

但是已经搜索了一些博客并阅读了几次文档,我很难理解这一点。阅读我的实际代码是有道理的,但如果不检查 JavaDoc 中的示例,我就无法自己推导出它。有人对如何更好地解释这一点有任何想法吗?

【问题讨论】:

    标签: lambda java-8 java-stream comparator


    【解决方案1】:

    Comparator.comparing 中的代码就是:

    Objects.requireNonNull(keyExtractor);
    
    return (Comparator<T> & Serializable)
            (c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));
    

    第一行只是检查参数不为空。

    第二行返回一个Comparator,它只是调用keyExtractor 函数来获取要比较的值,并使用它们的compareTo 方法进行比较。 comparing 声明中的泛型确保keyExtractor 必须实现Comparable

    在您的情况下,Meeting::getDate 方法引用将产生一个 keyExtractor 函数,它只调用 getDate 方法,所以

    keyExtractor.apply(c1)
    

    将执行

    c1.getDate()
    

    所以最终结果与您的原始代码基本相同。

    【讨论】:

    • 谢谢,所以在这种情况下 Comparator 是 Comparator
    • 是的T 将被推断为Calendar
    猜你喜欢
    • 1970-01-01
    • 2019-10-10
    • 1970-01-01
    • 2018-10-15
    • 1970-01-01
    • 2011-06-03
    • 2018-06-08
    • 2014-12-21
    相关资源
    最近更新 更多