乐字节-Java8新特性之函数式接口

120 阅读6分钟

什么时候可以使用Lambda?通常Lambda表达式是用在函数式接口上使用的。从Java8开始引入了函数式接口,其说明比较简单:函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。

3.1、语法定义

/*** 定义函数式接口* 接口上标注@FunctionalInterface 注解*/@FunctionalInterfacepublic interface ICollectionService {   /**    * 定义打印方法    */   void print();}

在Java8 以前,就已有大量函数式接口如下:

  • java.lang.Runnable

  • java.util.concurrent.Callable

  • java.security.PrivilegedAction

  • java.io.FileFilter

  • java.nio.file.PathMatcher

  • java.lang.reflect.InvocationHandler

  • java.beans.PropertyChangeListener

  • java.awt.event.ActionListener

  • javax.swing.event.ChangeListener

Java8 新增加的函数接口在java.util.function 包下,它包含了很多类,用来支持 Java的 函数式编程,该包中的函数式接口有:

序号接口 & 描述
1**BiConsumer**代表了一个接受两个输入参数的操作,并且不返回任何结果
2**BiFunction**代表了一个接受两个输入参数的方法,并且返回一个结果
3**BinaryOperator**代表了一个作用于于两个同类型操作符的操作,并且返回了操作符同类型的结果
4**BiPredicate**代表了一个两个参数的boolean值方法
5**BooleanSupplier**代表了boolean值结果的提供方
6**Consumer**代表了接受一个输入参数并且无返回的操作
7**DoubleBinaryOperator**代表了作用于两个double值操作符的操作,并且返回了一个double值的结果。
8**DoubleConsumer**代表一个接受double值参数的操作,并且不返回结果。
9**DoubleFunction**代表接受一个double值参数的方法,并且返回结果
10**DoublePredicate**代表一个拥有double值参数的boolean值方法
11**DoubleSupplier**代表一个double值结构的提供方
12**DoubleToIntFunction**接受一个double类型输入,返回一个int类型结果。
13**DoubleToLongFunction**接受一个double类型输入,返回一个long类型结果
14**DoubleUnaryOperator**接受一个参数同为类型double,返回值类型也为double 。
15**Function**接受一个输入参数,返回一个结果。
16**IntBinaryOperator**接受两个参数同为类型int,返回值类型也为int 。
17**IntConsumer**接受一个int类型的输入参数,无返回值 。
18**IntFunction**接受一个int类型输入参数,返回一个结果 。
19**IntPredicate**:接受一个int输入参数,返回一个布尔值的结果。
20**IntSupplier**无参数,返回一个int类型结果。
21**IntToDoubleFunction**接受一个int类型输入,返回一个double类型结果 。
22**IntToLongFunction**接受一个int类型输入,返回一个long类型结果。
23**IntUnaryOperator**接受一个参数同为类型int,返回值类型也为int 。
24**LongBinaryOperator**接受两个参数同为类型long,返回值类型也为long。
25**LongConsumer**接受一个long类型的输入参数,无返回值。
26**LongFunction**接受一个long类型输入参数,返回一个结果。
27**LongPredicate**R接受一个long输入参数,返回一个布尔值类型结果。
28**LongSupplier**无参数,返回一个结果long类型的值。
29**LongToDoubleFunction**接受一个long类型输入,返回一个double类型结果。
30**LongToIntFunction**接受一个long类型输入,返回一个int类型结果。
31**LongUnaryOperator**接受一个参数同为类型long,返回值类型也为long。
32**ObjDoubleConsumer**接受一个object类型和一个double类型的输入参数,无返回值。
33**ObjIntConsumer**接受一个object类型和一个int类型的输入参数,无返回值。
34**ObjLongConsumer**接受一个object类型和一个long类型的输入参数,无返回值。
35**Predicate**接受一个输入参数,返回一个布尔值结果。
36**Supplier**无参数,返回一个结果。
37**ToDoubleBiFunction**接受两个输入参数,返回一个double类型结果
38**ToDoubleFunction**接受一个输入参数,返回一个double类型结果
39**ToIntBiFunction**接受两个输入参数,返回一个int类型结果。
40**ToIntFunction**接受一个输入参数,返回一个int类型结果。
41**ToLongBiFunction**接受两个输入参数,返回一个long类型结果。
42**ToLongFunction**接受一个输入参数,返回一个long类型结果。
43**UnaryOperator**接受一个参数为类型T,返回值类型也为T。

用手指在上面向左(右)滑动,可以看完整。

对于Java8中提供的这么多函数式接口,开发中常用的函数式接口有三个:Predicate,Consumer,Function。

3.2、函数式接口实例

3.2.1、Predicate

java.util.function.Predicate接口定义了一个名叫test的抽象方法,它接受泛型T对象,并返回一个boolean。在需要表示一个涉及类型T的布尔表达式时,可以使用这个接口,通常称为断言性接口 。

使用Predicate接口实现字符串判空操作
@FunctionalInterfacepublic interface Predicate<T> {​   /**    * Evaluates this predicate on the given argument.    *    * @param t the input argument    * @return {@code true} if the input argument matches the predicate,    * otherwise {@code false}    */   boolean test(T t);  ...}​public static void main(String[] args) {   /**     * 借助Lambda 表达式实现Predicate test方法  */   Predicate<String> p01=(str)->str.isEmpty()||str.trim().isEmpty();   /**    * 测试传入的字符串是否为空     */   System.out.println(p01.test(""));   System.out.println(p01.test(" "));   System.out.println(p01.test("admin"));}

测试结果:

3.2.2、Consumer

java.util.function.Consumer接口定义了一个名叫accept的抽象方法,它接受泛型T,没有返回值(void)。如果需要访问类型T的对象,并对其执行某些操作,可以使用这个接口,通常称为消费性接口。

使用Consumer实现集合遍历操作
@FunctionalInterfacepublic interface Consumer<T> {​   /**    * Performs this operation on the given argument.    *    * @param t the input argument    */   void accept(T t);  ...}​​/*** 借助Lambda表达式实现Consumer accept方法*/Consumer<Collection> c01 = (collection) -> {if (null != collection && collection.size() > 0) {for (Object c : collection) {System.out.println(c);}}};​List<String> list = new ArrayList<String>();list.add("诸葛亮");list.add("曹操");list.add("关羽");​// 遍历list 输出元素内容到控制台c01.accept(list);

3.2.3、Function

java.util.function.Function<T, R>接口定义了一个叫作apply的方法,它接受一个泛型T的对象,并返回一个泛型R的对象。如果需要定义一个Lambda,将输入的信息映射到输出,可以使用这个接口(比如提取苹果的重量,或把字符串映射为它的长度),通常称为功能性接口。

使用Function实现用户密码 Base64加密操作
@FunctionalInterfacepublic interface Function<T, R> {​   /**    * Applies this function to the given argument.    *    * @param t the function argument    * @return the function result    */   R apply(T t);}​​// 实现用户密码 Base64加密操作Function<String,String> f01=(password)->Base64.getEncoder().encodeToString(password.getBytes());// 输出加密后的字符串System.out.println(f01.apply("123456"));

加密后结果如下:

3.2.4、Supplier

java.util.function.Supplier接口定义了一个get的抽象方法,它没有参数,返回一个泛型T的对象,这类似于一个工厂方法,通常称为功能性接口。

使用Supplier实现SessionFactory创建
@FunctionalInterfacepublic interface Supplier<T> {​   /**    * Gets a result.    *    * @return a result    */   T get();}​/*** 产生一个session工厂对象*/Supplier<SessionFactory> s = () -> {   return new SessionFactory();};​s.get().info();