Java,为什么collections.sort()仍然适用于非比较器类型的参数?

时间:2017-08-20 06:32:56

标签: java lambda collections

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

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

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

但是当我学习 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接口无关,我无法理解为什么这样有效?任何人都能解释一下吗?

非常感谢。

3 个答案:

答案 0 :(得分:7)

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

这是一种较短的写作方式:

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

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

答案 1 :(得分:1)

您不需要在此处编写明确的字符串比较器。

只需按照说明操作即可。

NullPointerException

顺便说一下,@ Eran已经解释过,在你的场景中,compareWord和compare的方法签名相同。

答案 2 :(得分:0)

Comparator界面是@FunctionalInterface

  

功能接口是一个代表单个功能合同的接口。 [...]

     

对于接口I,让M是作为I的成员的抽象方法集合,它们与Object类的任何公共实例方法没有相同的签名。然后,如果在M中存在m方法m,则我是一个函数接口,其中以下两个都为真:

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

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

  •   
     

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

它进一步提到Comparator为例:

  

功能接口的定义排除了接口中的方法,这些方法也是Object中的公共方法。这是为了允许像java.util.Comparator这样的接口的功能处理,它声明了多个抽象方法,其中只有一个是真正的“新” - int compare(T,T)。另一种方法 - 布尔等于(Object) - 是一个抽象方法的显式声明,否则将被隐式声明,并将由实现该接口的每个类自动实现。

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

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