当前位置: 首页 > 知识库问答 >
问题:

Java,为什么选择集合。sort()仍适用于非comparator类型的参数?

房光临
2023-03-14

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

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

排序中的第二个参数应该是实现比较器接口及其比较方法的对象。

但当我学习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个答案

姜旭
2023-03-14

比较器接口是一个功能接口:

函数式接口是[...]表示单个函数契约的接口。[...]

对于接口I,设M为抽象方法集,这些抽象方法是I的成员,与类对象的任何公共实例方法没有相同的签名。那么,如果m中存在一个方法m,则I是一个函数接口,对于该方法m,以下两项均为真:

>

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

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

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

    它进一步提到比较器作为示例:

    函数式接口的定义排除了接口中也是Object中公共方法的方法。这是为了允许对接口进行函数式处理,例如java.util.比较器,它声明了多个抽象方法,其中只有一个是真正的“新”——int比较(T, T)。另一个方法——布尔等于(Object)——是抽象方法的显式声明,否则该方法将被隐式声明,并将由实现该接口的每个类自动实现。

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

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

  • 彭博厚
    2023-03-14

    这里不需要编写显式字符串比较器。

    只要做到以下几点,它就会工作得很好。

    Collections.sort(lst);
    

    按照@Eran的解释,在您的场景中,关于compareWord和compare的方法签名是相同的。

    山阳辉
    2023-03-14

    int-compareWord(字符串a,字符串b)比较器的int-compare(字符串o1,字符串o2)方法具有相同的签名

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

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

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

     类似资料:
    • 问题内容: 您在JPA域模型中使用以下哪种收集类型以及原因: 我想知道是否有一些基本规则。 更新 我知道a 和a 之间的区别。A 允许重复且具有顺序,而a 不能包含重复元素且未定义顺序。我在JPA的背景下问这个问题。如果严格遵循定义,那么您应该始终使用类型,因为您的集合存储在关系数据库中,那里您不能重复,并且您自己定义了一个顺序,即Java中的顺序是不一定保留在数据库中。 例如,大多数时候我使用类

    • 问题内容: 根据这个答案 我试图在我的桌子上创建一个Select for 但是我对位类型示例sqlfiddle遇到了问题,如您所见,它应该返回4行,但它仅返回3行,所以我想念什么? 问题答案: 这是因为您可以将as作为列的值。而且SQL具有三值逻辑,因此检查将返回,而不是(如您期望的那样)。我认为此查询将为您提供帮助:

    • 问题内容: 在Java背景下玩Swift,为什么要选择Struct而不是Class?似乎它们是同一回事,但Struct提供的功能较少。为什么选择它呢? 问题答案: 根据非常流行的WWDC 2015演讲《 Swift中的面向协议的编程》(视频,成绩单),Swift提供了许多功能,这些功能在许多情况下都比类更好。 如果结构相对较小且可复制,则结构是可取的,因为与在类中多次引用相同实例相比,复制要安全得

    • 我想知道用类型化语言(如Haskell或Idris)表达智能合约的最佳方式是什么(例如,您可以编译它以在以太坊网络上运行)。我主要关心的是:什么类型可以捕获合同所能做的一切? 一个简单的解决方案是将协定定义为类型的成员。这种类型类似于Haskell的,但它不支持系统调用,而是包括区块链调用,即,它将支持从区块链状态读取和写入区块链状态、调用其他契约、获取块数据等。 这显然足以执行任何合同,但是:

    • 为什么只适用于s而不适用于s?有什么特别的原因吗?