函数式接口 && lambda && Stream

函数式接口

内置常用的函数式接口位于java.util.function.*包中。
常用函数式接口Function、consumer、predicate、supplier等。

Lambda表达式 && FunctionalInterface

接口由@FunctionalInterface注解标注,该注解仅仅为定义约束,不注解也不会影响功能(从code规范上应该要注解),只要满足函数式接口定义都属于函数式接口(接口有且只能有个一个抽象方法)。

函数式接口为普通接口增加了更严格的约定;
lambda表达式是匿名类的简化书写形式,但lambda只能用于函数式接口;
即lambda表达式只能基于函数式接口而存在,因此是类接口实例化的简化书写形式,更简洁、方便和灵活。

@FunctionalInterface
public interface PrintFunction<T> {
    void print(T t);
}

上面定义了一个函数式接口,有且只有一个抽象方法。接口使用泛型T,便于实现不同类型的参数打印。

        PrintFunction<String> pf = new PrintFunction<String>() {
            @Override
            public void print(String s) {
                System.out.println(s);
            }
        };
        pf.print("a");  //a

上面通过匿名类方式直接实现了接口并实例化,并使用方法打印“a”。

        PrintFunction<String> pf = (s) -> {
          System.out.println(s);
        };
        pf.print("b");

上面通过lambda方式实现了接口并实例化,并调用方法print打印“b”,(s) 为入参,大括号内是方法的实现。大括号结束有分号。由于只有一个语句,可以省略{},只有一个参数,可以省略()。即:s -> System.out.println(s) 。

对比看lambda也就是书写形式上简化了。也因为lambda的这种书写形式,所以要求接口有且仅有一个抽象方法,便于直接用 “->” 实现。

这个lambda表达式是基于PrintFunction接口的定义来写的,编译器会按照接口定义检查表达式书写是否正确。

        PrintFunction<String> pf = System.out::println;
        pf.print("b");  //b

上面代码是对lambda表达式更简化的书写,System.out是指定的类,println是指定的方法,该方法只有一个入参,正好接口方法只会传入一个入参,因此可以正好匹配。所以只需要写明具体类的具体方法即可,编译器会自动识别及解析出来。

lambda表达式一定是基于某个接口定义而书写的,其他书写格式可参考lambda语法。

Function

接收T对象,返回R对象。
先看源码(去掉了注释)

@FunctionalInterface
public interface Function<T, R> {
    R apply(T t);
    
    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
        Objects.requireNonNull(before);
        return (V v) -> apply(before.apply(v));
    }

    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t) -> after.apply(apply(t));
    }
    
    static <T> Function<T, T> identity() {
        return t -> t;
    }
}

Function接口包含两个default方法及一个static方法。
default方法compose:先执行before入参的函数,再执行自身函数;
default方法andThen:先执行自身函数,再执行after入参的函数。

        Function<Integer, Integer> f = s -> s++;
        Function<Integer, Integer> g = s -> s * 2;

        /**
         * f.apply( g.apply(1) )
         */
        System.out.println(f.compose(g).apply(1)); // 2

使用该函数式接口时,先定义函数体,再调用该函数体方法执行(与匿名类只是书写形式不一样),lambda简洁的形式,让程序逻辑更灵活。

如上代码,f.compose(g),将g函数作为入参,与当前函数的方法一起构成了复杂的方法,该复杂的方法:

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值