【问题标题】:Java, why collections.sort() still works with non-comparator typed argument?Java,为什么 collections.sort() 仍然适用于非比较器类型的参数?
【发布时间】:2017-08-20 06:32:56
【问题描述】:

我知道在java Collections类中,有一个静态方法sort:

sort(List<T> list, Comparator<? super T> c**)

sort 中的第二个参数应该是一个实现了 Comparator 接口的对象,它是 compare 方法。

但是当我学习lambda的方法参考时,我看到了这个例子:

public class Test 
{
     public static void main(String[] args) 
    {
        new Test().sortWord();  
    }

    public void sortWord()
    {
        List<String> lst = new ArrayList<>();
        lst.add("hello");
        lst.add("world");
        lst.add("apple");
        lst.add("zipcode");

        Collections.sort(lst, this::compareWord);

        System.out.println(lst);
    }

    public int compareWord(String a, String b)
    {
       return a.compareTo(b);
    }

}

这是实例方法的方法引用示例。 compareWord 方法与 Comparator 接口无关,我不明白为什么会这样?谁能解释一下?

非常感谢。

【问题讨论】:

    标签: java lambda collections


    【解决方案1】:

    int compareWord(String a, String b)Comparator&lt;String&gt; 接口的int compare(String o1, String o2) 方法具有相同的签名。因此,它可以用作该接口的实现。

    这是一种较短的写法:

    Collections.sort(lst, new Comparator<String> () {
                         public int compare (String o1, String o2) {
                             return compareWord(o1,o2);
                         }
                     });
    

    在 Java 8 中,任何函数式接口,例如 Comparator(即具有单个抽象方法的接口)都可以使用具有与该接口抽象方法的签名匹配的签名的方法的方法引用来实现。

    【讨论】:

      【解决方案2】:

      你不需要在这里写一个显式的字符串比较器。

      只需执行以下操作,它应该可以正常工作。

      Collections.sort(lst);
      

      @Eran 已经解释过,在您的场景中, compareWord 和 compare 的方法签名相同。

      【讨论】:

        【解决方案3】:

        Comparator 接口是@FunctionalInterface

        功能接口是 [...] 表示单个功能合约的接口。 [...]

        对于接口 I,令 M 是一组抽象方法,它们是 I 的成员,与 Object 类的任何公共实例方法没有相同的签名。那么,如果在 M 中存在一个方法 m 并且满足以下两个条件,则 I 是一个函数式接口:

        • m 的签名是 M 中每个方法签名的子签名(第 8.4.2 节)。

        • m 对于 M 中的每个方法都是可替换的返回类型(第 8.4.5 节)。

        除了通过声明和实例化类(§15.9)来创建接口实例的常规过程之外,还可以使用方法引用表达式和 lambda 表达式(§15.13§15.27)来创建功能接口实例。

        还以Comparator为例:

        函数式接口的定义不包括接口中的方法,这些方法也是 Object 中的公共方法。这是为了允许对像 java.util.Comparator 这样声明多个抽象方法的接口进行功能处理,其中只有一个是真正“新的”——int compare(T,T)。另一种方法 - boolean equals(Object) - 是抽象方法的显式声明,否则将被隐式声明,并且将由实现该接口的每个类自动实现。

        除了@Eran 提供的匿名类示例和问题中的方法引用表达式之外,lamba 表达式也可以工作:

        Collections.sort(lst, (a, b) -> ...);
        

        【讨论】:

          猜你喜欢
          • 2018-11-27
          • 1970-01-01
          • 2010-10-19
          • 2020-07-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多