JAVA1.8新特性-函数式接口

  1. JDK1.8中引入了用于函数式编程的支持。java中的函数式接口指:有且只有一个方法的接口。函数式接口是适用于函数式编程场景的接口。而java中的函数式编程指的就是Lamda,所以函数式接口就是可以适用于Lamda使用的接口。只要确保接口中有且仅有一个抽象方法,java中的Lamda才能顺利推导。
    Java官方专门提供了@FunctionalInterface注解用于确保接口中只有一个方法,比如自定义一个函数式接口,当然如果一个接口符合函数式编程规范(及接口中只有一个方法)即可,因此不加此注解也是可以的,@FunctionalInterface注解只是起到强制检查的作用。
@FunctionalInterface public interface Function{ void method(String str); }

Java中的Lamda可以被当作匿名内部类的替代写法,但是两者的底层实现原理是不同的。
public class Demo { private static void method(String str, Function lambda) { lambda.method(str); } public static void main(String[] args) { method("张三",s -> System.out.println(s) ); } }

Lamda表达式简化了传统java编码的写法就比如集合的排序可以这么写
List list = new ArrayList<>(); list.add(10); list.add(42); list.add(52); list.add(7); list.add(48); list.add(99); list.add(5); Collections.sort(list,(a,b) -> a-b); System.out.println("list = " + list);

  1. JDK提供了大量常用的函数式接口以丰富Lambda的典型使用场景,它们主要在 java.util.function 包中被提供。 下面是简单的几个接口及使用示例。
    2.1 Supplier接口
    当Lamdba表达式需要“对外提供”一个符合泛型类型的对象数据,可以使用该接口
private static int getMax(Supplier fun){ return fun.get(); } public static void main(String[] args) { // 求数组最大值 int arr[] = {2,3,4,52,333,23}; int max = getMax(() -> { int maxV =arr[0]; for (int i =1; i maxV){ maxV = val; } } return maxV; }); }

2.2 Consum接口
java.util.function.Consumer 接口则正好与Supplier接口相反,它不是生产一个数据,而是消费一个数据, 其数据类型由泛型决定。
private static void consumString(Consumer fun){ fun.accept("I am EmonH"); } public static void main(String[] args) { consumStrings(s -> System.out.println("s = " + s.toLowerCase())); }

【JAVA1.8新特性-函数式接口】默认方法:andThen
如果一个方法的参数和返回值全都是 Consumer 类型,那么就可以实现效果:消费数据的时候,首先做一个操作, 然后再做一个操作,实现组合。而这个方法就是 Consumer 接口中的default方法 andThen 。
private static void consumStrings(Consumer fun1,Consumer fun2){ fun1.andThen(fun2).accept("I am EmonH"); } public static void main(String[] args) { consumStrings(s -> System.out.println("s = " + s.toLowerCase()), s -> System.out.println("s = " + s.toUpperCase())); }

2.3 Predicate接口
有时候我们需要对某种类型的数据进行判断,从而得到一个boolean值结果。这时可以使用 java.util.function.Predicate 接口。其默认方法有test,and,or,negate
private static void predicateInteger1(Predicate fun1){ boolean ispositiveNum = fun1.test(2) && fun1.test(4); System.out.println(ispositiveNum ?"是" :"否"); }

// 并
private static void predicateInteger2(Predicate fun1,Predicate fun2){ boolean ispositiveNum = fun1.test(2) && fun2.test(2); System.out.println(ispositiveNum ?"是" :"否"); }

// 并
private static void predicateInteger3(Predicate fun1,Predicate fun2){ boolean ispositiveNum = fun1.and(fun2).test(2); System.out.println(ispositiveNum ?"是" :"否"); }

// 或
private static void predicateInteger4(Predicate fun1,Predicate fun2){ boolean ispositiveNum = fun1.or(fun2).test(2); System.out.println(ispositiveNum ?"是" :"否"); }

// 取反
private static void predicateInteger5(Predicate fun1){ boolean ispositiveNum = fun1.negate().test("EmonH"); System.out.println(ispositiveNum ?"是" :"否"); } public static void main(String[] args) { predicateInteger1(s -> s >4); predicateInteger2(s -> s ==4,s -> s ==4); predicateInteger3(s -> s ==4,s -> s ==4); predicateInteger4(s -> s ==4,s -> s ==4); predicateInteger5(s -> s.length() >4); }

2.4 Function接口
java.util.function.Function 接口用来根据一个类型的数据得到另一个类型的数据,前者称为前置条件, 后者称为后置条件。
// Function 接口中主要的抽象方法为: R apply(T t) ,根据类型T的参数获取类型R的结果。 // 使用的场景例如:将 String 类型转换为 Integer 类型。 private static void method(Function function,String str){ Integer num = function.apply(str); System.out.println("num = " + num); }

// 默认方法:andThen
// Function 接口中有一个默认的 andThen 方法,用来进行组合操作。
private static void method2(Function function,Function function2,String str){ Integer num = function.andThen(function2).apply(str); System.out.println("num = " + num); }

public static void main(String[] args) { String str ="12356"; method(s->Integer.parseInt(s),str); String str2 ="赵丽颖,20"; method2(s->Integer.parseInt(s),i-> i*100,str2.split(",")[1]); }

    推荐阅读