函数式接口的实现方法之一:使用lambda表达式

一、问题的提出

        实现自定义类对象之间的比较可以使用向Collections.sort或Arrays.sort方法传递一个Comparator函数式接口的方法实现,而实现函数式接口有多种方法,下面将主要阐述使用lambda表达式的实现方法。

        依然使用不可变类Interval:

/**
 * An interval defind by start and end, start <= end, 
 * represents the section from start to end including both start and end.
 * 
 * Interval is immutable
 */
public class Interval {
    private final long start;
    private final long end;

二、概述

        查看java API可以了解到FunctionalInterface的基本信息:

        根据API的描述,函数式接口是只有一个抽象方法的接口,这使它能够以一种简单的形式实现在lambda表达式里。

        实现函数式接口还可以通过方法引用或构造引用。

三、使用lambda表达式实现函数式接口

        函数式接口作为一种特殊接口,可以像实现普通接口那样实现它,如为其写一个实现类,或使用内部匿名类:

         /**内部匿名类 */
        Collections.sort(list, new Comparator<Interval>() {
            @Override
            public int compare(Interval o1, Interval o2) {
                if (o1.getStart() < o2.getStart())
                    return -1;
                else if (o1.getStart() > o2.getStart())
                    return 1;
                else
                    return 0;
            }
        });

        函数式接口的特殊定义意味着它可以用一种不同的方式实现--在lambda表达式中实现。

第一种:

Collections.sort(list, (Interval o1, Interval o2) -> compareFunc(o1.getStart(), o2.getStart()));

         其中compareFunc定义如下:

public static int compareFunc(long l1, long l2) {
        if (l1 < l2)
            return -1;
        else if (l1 > l2)
            return 1;
        else
            return 0;
    }

        在底层,Collections.sort方法会接收一个实现了Comparator<Interval>的某个类的对象,调用compare方法时会执行这个lambda表达式。

        lambda表达式的类型是取决于上下文的,称为“目标类型”,甚至参数的类型也可以从上下文中获取而无需声明。

第二种:

Comparator<Interval> cmp = (o1, o2) -> compareFunc(o1.getStart(), o2.getStart());
Collections.sort(list, cmp);

        声明一个函数式接口引用,指向lambda表达式,这里的形参不用声明类型,因为可以从cmp的声明中得知它们是Interval类的。

        这也是一种存储lambda表达式的方法。

第三种:

BiFunction<Interval, Interval, Integer> comp = (Interval o1, Interval o2) -> compareFunc(o1.getStart(),
                o2.getStart());

        使用默认函数式接口BiFunction保存lambda表达式,它的声明表示这是一个需要两个Interva形参、返回值为Integer的方法。

        但这种方法不能用来排序,因为Collections或Arrays的sort方法不会接收一个函数式接口作为参数。

四、函数式接口与Object

        函数式接口是不同于Object的,即使在底层lambda表达式会作为某个类的对象存在,但其类型终究只是不确定的“目标类型”,这意味着下面的赋值操作是错误的:

Object o = (o1, o2) -> compareFunc(o1.getStart(), o2.getStart());

        同样,lambda表达式也不能作为Object参数传递,下面的语句也是错误的:

System.out.println((o1, o2) -> compareFunc(o1.getStart(), o2.getStart()));

        这时就需要显式的转换成函数式接口再赋值给Object:

Object o = (Comparator<Interval>) (o1, o2) -> compareFunc(o1.getStart(), o2.getStart());
System.out.println((Comparator<Interval>) (o1, o2) -> compareFunc(o1.getStart(), o2.getStart()));

五、小结

        本文简单阐述了用lambda表达式实现函数式接口的方法,lambda表达式的类型是取决于上下文的,不同于Object。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值