函数式接口
函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。
函数式接口可以被隐式转换为lambda表达式。
这些接口在java.util.function包中。
@FunctionalInterface
Java 8 为函数式接口引入了一个新注解“@FunctionalInterface”,主要用于编译级错误检查,加上该注解,当你写的接口不符合函数式接口定义的时候,编译器会报错。
加不加“@FunctionalInterface”对于接口是不是函数式接口没有影响,该注解只是提醒编译器去检查该接口是否仅包含一个抽象方法。
请注意,“@FunctionalInterface”不是必需的,但对于为此设计的接口而言,使用它是比较好的做法。它就像是“@Override”标注表示方法被重写了。
名称 | 类型 | 描述 | 作用 |
---|---|---|---|
Consumer | Consumer | 接收T对象,不返回值 | 消费某个对象 |
Predicate | Predicate | 接收T对象并返回boolean | 判断对象是否符合某个条件 |
Function | Function<T,R> | 接收T对象,返回R对象 | 实现一个”一元函数“,即传入一个值经过函数的计算返回另一个值。 |
Supplier | Supplier | 提供T对象(例如工厂),不接收值 | 创建一个对象(工厂类) |
UnaryOperator | UnaryOperator | 接收T对象,返回T对象 | UnaryOperator继承了Function,与Function作用相同 不过UnaryOperator,限定了传入类型和返回类型必需相同 |
BiConsumer | BiConsumer<T, U> | 接收T对象和U对象,不返回值 | 同 Consumer ,接收两个参数 |
BiPredicate | BiPredicate<T, U> | 接收T对象和U对象,返回boolean | 同 Predicate ,接收两个参数 |
BiFunction | BiFunction<T, U, R> | 接收T对象和U对象,返回R对象 | 同 Function ,接收两个参数 |
BinaryOperator | BinaryOperator | 接收两个T对象,返回T对象 | 同 UnaryOperator ,接收两个参数 |
Consumer
使用场景:
Iterable 接口的 forEach 方法需要传入 Consumer,大部分集合类都实现了该接口,用于返回 Iterator 对象进行迭代。
设计思想:
开发者调用``ArrayList.forEach``时,一般希望自定义遍历的消费逻辑,比如:输出日志或者运算处理等。
处理逻辑留给使用者,使用灵活多变。
多变的逻辑能够封装成一个类(实现Consumer接口),将逻辑提取出来。
Predicate
使用场景:
ArrayList的removeIf(Predicate) // 删除符合条件的元素
如果条件硬编码在 ArrayList 中,它将提供无数的实现,但是如果让调用者传入条件,这样 ArrayList 就可以从复杂和无法猜测的业务中解放出来。
设计思想:
提取条件,让条件从处理逻辑脱离出来,解耦合
Function<T, R>
使用场景:
V HashMap.computeIfAbsent(K , Function<K, V>) // 简化代码,如果指定的键尚未与值关联或与null关联,使用函数返回值替换。
<R> Stream<R> map(Function<? super T, ? extends R> mapper); // 转换流
设计思想:
一元函数的思想,将“转换逻辑”提取出来,解耦合
Supplier
使用场景:
Optional.orElseGet(Supplier<? extends T>) // 当this对象为null,就通过传入supplier创建一个T返回。
设计思想:
封装工厂创建对象的逻辑
UnaryOperator
使用场景:
List.replaceAll(UnaryOperator) // 该列表的所有元素替换为运算结算元素
Stream.iterate(T,UnaryOperator) // 重复对seed调用UnaryOperator来生成元素
设计思想:
一元函数的思想,将“同类转换逻辑”提取出来,解耦合
谓词
谓词接口包括三个方法:negate、and和or,让你可以重用已有的Predicate来创建更复杂的谓词。