Lambda表达式

231 阅读3分钟

记录一下Lambda表达式的东西,

一、定义

Consumer:消费者,实现accept(T t)方法

Function:apply方法,传参T,返回R

Predicate: 返回true或者false,实现test方法

Suppier: 返回一个对象,需要实现get方法。类似生产者,所以每次必须返回一个对象

基础的方法简单,需要记忆一下。

BinaryOperator:继承自BiFunction。

Consumer、Function接口都默认实现addThen方法,链式传递。其他的接口,看名字基本知道具体的作用,例如LongConsumer,参数为long类型。以Bi开头表示两个参数的意思,例如BiConsumer,BiPredicate。

函数接口(只有一个需要实现的方法,并且方法上面有@FuntionaIterface注解)的实现类,都可以使用Lambda表达式。

二、箭头函数

箭头函数主要用来简化开发,本质是一种语法糖,生成一个接口的实现类。比如定义一个Runnable 接口可以采用箭头函数方式:

 Runnable runnable=()->System.out.println(hello);

所以可以把箭头函数理解成为是一个实现了某个接口方法的函数,箭头函数能够模拟的接口只允许有一个方法,default和static方法不做限制

//其实这种写法,不太好懂。可以把箭头函数理解成创建一个接口的实现类就好了

下面来个难一个一点的箭头函数:

public interface Consumer<T> {
       void accept(T t);   
       default Consumer<T> andThen(Consumer<? super T> after) {      
        Objects.requireNonNull(after);
        return (T t) -> { accept(t); after.accept(t); };
    }
}

这个是jdk8中的consumer接口,看这里addThen写法,return的时候,return的是一个Consumer,所以最有采用了箭头函数又生成了一个Consumer的实现类。

三、forEach

遍历操作,这种第一感觉就是要实现consumer接口的。

看下集合中forEach中的实现:

凡是继承Iterable接口的方法都具有forEach方法,因为forEach方法是Iterable的default方法。

default void forEach(Consumer<? super T> action) {
   Objects.requireNonNull(action);
   for (T t : this) {
     action.accept(t);   }
 }

最终其实还是走的for循环。HashMap采用的是类似的做法,把forEach作为map的default方法

三、Optional

jdk8新增一个工具类,可以辅助判空操作,一定要用起来,现在很多源码里面都有这个了,起码skywalking、mybatis-plus里面都有用到。

这个类的基本设计思路就是对传入进来的对象进行包装(java里面有个专业的名词叫做wrap),对包装之后的对象进行转换(map)、过滤(filter)、默认值(orElse)、获取(get)、异常(orElseThrow)、是否存在(ifPresent)。

这个工具类里面基本Consumer、Function、Supplier、Predicate基本都有涉及,是复习Lambda的好方法

  • Consumer:ifPresent方法可以传入一个Consumer接口的实现类,
  • Function: map,flatMap接口实现可以需要用到
  • Supplier:orElse方法传入Suppier实现类
  • Predicate: filter方法需要传入Predicate接口实现类

看一下filter的实现

public Optional<T> filter(Predicate<? super T> predicate) { 
   Objects.requireNonNull(predicate); //判空操作,fast-fail
   if (!isPresent())    
    return this;   //当前对象为空,直接返回
   else      
  return predicate.test(value) ? this : empty();  //按照传入条件进行比较
}

Optional相当于是对一个对象进行wrap,有文章说Optioanl是基于编译时的检查,这个地方不是太明白。

四、ForkJoin并行

五、Stream

//Lambda的重头戏来了

Stream是对Iterator迭代器的加强,Stream支持并行操作

五、总结