函数式接口
概念
函数式接口在Java中指的是 : 有且仅有一个抽象方法的接口就称为函数式接口.
函数式接口, 适用于函数式编程的, 在Java当中的函数式编程体现在Lambda , 所以函数式接口就是用来服务Lambda表达式. 只有确保接口当中有且仅有一个抽象方法 , Java中的Lambda才能顺利进行推导.
备注: "语法糖"是指使用更加便利方便,但是原理不变的代码语法. 就比如遍历集合时使用for - each语法 , 其实底层使用的是迭代器, 这便是语法糖.
格式:
只有确保接口当中有且仅有以各抽象方法即可:
修饰符 interface InterfaceName{ // 只能定义一个抽象方法 public abstract 返回值类型 方法名称(参数列表); // 还可以定义其他的非抽象方法 }
@FunctionalInterface注解
与@Override注解作用类似 , JDK 8中专门为函数式接口引入的一个新注解@FunctionalInterfact , 该注解主要定义在接口上 . 一旦在接口上使用该注解,编译器将会强制检查该接口是不是一个函数式接口, 该接口中是不是有且仅有一个抽象方法 , 如果不是 , 编译报错.
自定义函数式接口的用途 , 一般用于方法的参数和返回值上.
函数式编程
能够在兼顾Java的面向对象特性基础上 , 通过Lambda表达式与后面的方法引用 , 为开发者打开函数式编程的大门.
Lambda的延迟加载
有些场景的代码运行执行后,结果不一定会被使用到 , 从而造成性能的浪费 . 而Lambda表达式是延迟执行的,真好可以解决此问题,提升性能
使用Lambda作为方法的参数和返回值
在Java当中, Lambda表达式是作为匿名内部类的替代品 , 如果一个方法的参数是一个函数式接口类型, 那么可以使用Lambda表达式进行替代.
java.lang.Runnable接口就是一个函数式接口
常用的函数式接口
JDK提供了大量常用的函数式接口, 丰富Lambda表达式的使用场景,他们主要在java.util.function包中被提供.
Supplier接口
java.util.function.Supplier<T>接口 , 该接口有且仅有一个无参的方法: T get() . 用来获取一个泛型参数指定类型的对象数据 . 由于该接口是一个函数式接口 , 所以我们可以使用Lambda表达式来操作他
Supplier<T>接口被称之为生产型接口 ,指定接口的泛型是什么类型 , 那么接口中的get()方法就会生产什么类型的数据 .
Consumer 接口
java.util.function.Consumer<T>接口刚好和Supplier接口相反 , 他不是用来生产一个数据 , 而是消费一个数据.
数据的类型由泛型来指定
accept方法
意思就是消费一个指定泛型的数据.
默认的方法: andThen
如果一个方法的参数和返回值全都是Consumer类型 , 那么就可以实现这样的效果: 消费数据的时候 , 首先做一个生产的操作 , 在做一个消费的操作 , 实现组合 .可以通过Consumer接口当中的默认方法: andThen来实现.
通过查看源码得知:andThen方法不允许传入一个null对象否则就会抛出空指针异常。
要想把两次消费的动作连接起来,需要传入两个Consumer接口,通过andThen
方法实现一步一步执行消费动作。
Stream流
在Java 1.8中,由于Lambda表达式这种函数式编程 JDK引入了一个全新的概念"Stream流"
。用于解决已有集合类库的一些弊端的。
当我们需要对集合当中的元素进行操作的时候,总是需要对集合循环遍历,再次循环遍历,....一定需要这样做吗?
不一定,它只是用来找到你需要元素的一种方式,并不是目的。目的就是想要去除想要的元素并且循环打印展示出来。以往的方式就是每次循环都需要从头开始遍历,下一次循环还是从头开始。
JDK 1.8可以使用Lambda表达式的衍生物Stream流来优化你遍历集合的方式。
一般我们把流式思想称之为"生产流水线"