带多方法的接口能否用匿名函数?Comparator与Lambda适配疑问
关于函数式接口与Lambda表达式的问题解答
一、若Predicate接口包含多个方法会出现什么情况?
首先明确:Predicate<T>是Java定义的函数式接口,这类接口的核心要求是仅包含一个抽象方法(Object类自带的方法除外)。
- 如果给
Predicate<T>新增一个参数签名不同的抽象方法,那它就不再是函数式接口。此时想用Lambda表达式实现这个接口会直接编译报错——因为Lambda只能对应单个抽象方法的实现,无法同时处理多个抽象方法的逻辑。 - 要是新增的方法和原有的
test(T t)参数签名完全相同,这属于方法重复定义,不管是不是函数式接口,代码本身就编译不过,和Lambda无关。
二、Comparator接口包含多个方法,Lambda如何表示equals(Object obj)?
Comparator<T>虽然看起来有多个方法,但它依然是函数式接口——因为它只有一个抽象方法int compare(T o1, T o2),其他方法要么是:
- 继承自Object类的
equals(Object obj):所有接口都会隐式继承Object的方法,但这些方法不算抽象方法(因为Object类已经提供了默认实现); - Java 8及以后新增的默认方法(比如
reversed())或静态方法(比如naturalOrder()):这类方法带有具体实现,不影响函数式接口的判定。
当你用Lambda表达式传给TreeSet(Comparator<? super E> comparator)构造器时,Lambda只需要实现compare方法即可,equals方法不需要额外处理:
- Lambda表达式会被转换成
Comparator的实例,这个实例的equals方法默认继承自Object类的equals实现,用来比较两个对象的内存地址; - 如果你真的需要自定义
equals逻辑,不能用Lambda,得改用匿名内部类实现Comparator并手动重写equals方法,但TreeSet排序时根本不会用到Comparator的equals方法,它只依赖compare方法确定元素顺序和唯一性,所以绝大多数场景下不需要管equals。
代码示例
interface Predicate<T> { boolean test(T t); } public static void printPersons( List<Person> roster, Predicate<Person> tester) { for (Person p : roster) { if (tester.test(p)) { p.printPerson(); } } } printPersons( roster, (Person p) -> p.getGender() == Person.Sex.MALE && p.getAge() >= 18 && p.getAge() <= 25 );
内容的提问来源于stack exchange,提问作者notaorb
相关产品推荐
相关产品推荐

