Java 8 函数式编程
- Lambda表达式
λ表达式本质上是一个匿名方法。让我们来看下面这个例子: public int add(int x, int y) { return x + y; } 转成λ表达式后是这个样子: (int x, int y) -> x + y;
λ表达式的类型,叫做“目标类型(target type)”。λ表达式的目标类型是“函数接口(functional interface,FI)”,这是Java8新引入的概念。
它的定义是:一个接口,如果只有一个显式声明的抽象方法,那么它就是一个函数接口。一般用@FunctionalInterface标注出来(也可以不标)。
我们常见的Runable、Comparable等都算是FI。注意这里的显示声明只的是在这个接口里面声明,比如说继承自Object中的方法就不算显示声明的方法。
需要记住的一件事是:默认方法与静态方法并不影响函数式接口的契约,可以任意使用:
你可以用一个λ表达式为一个函数接口赋值: Runnable r1 = () -> {System.out.println("Hello Lambda!");};
Runnable r1 = () -> {System.out.println("Hello Lambda!")}; //只有一条语句的时候可以省略一个分号。
- lambda表达式通常以
(argument)->(body)的格式,其中argument表示抽象方法的参数,body是抽象方法实现的函数体的内容
(Type1 arg1,Type2 arg2...)->{body} //参数类型可以省略 (arg1,arg2...) -> {body}
- 参数可以是零个或多个
- 参数类型可指定,可省略(根据表达式上下文推断)
- 参数包含在圆括号中,用逗号分隔
- 表达式主体可以是零条或多条语句,包含在花括号中
- 表达式主体只有一条语句时,花括号可省略
- 表达式主体有一条以上语句时,表达式的返回类型与代码块的返回类型一致
- 表达式只有一条语句时,表达式的返回类型与该语句的返回类型一致
Java8 API中新增了许多函数式接口: -
函数式接口 函数描述符 原始类型特化 Predicate<T>
T -> boolean IntPredicate, LongPredicate, DoublePredicate
Consumer<T>
T -> void IntConsumer, LongConsumer, DoubleConsumer
Function<T,R>
T -> R IntFunction<R>, IntToDoubleFunction, IntToLongFunction, LongFunction<R>, LongToDoubleFunction, LongToIntFunction, DoubleFunction<R>, ToIntFunction<T>, ToDoubleFunction<T>, ToLongFunction<T>
Supplier<T>
() -> T BooleanSupplier, IntSupplier, LongSupplier, DoubleSupplier
UnaryOperator<T>
T -> T IntUnaryOperator, LongUnaryOperator, DoubleUnaryOperator
BinaryOperator<T>
(T,T) -> T IntBinaryOperator, LongBinaryOperator, DoubleBinaryOperator
BiPredicate<L,R>
(L,R) -> boolean BiConsumer<T,U>
(T,U) -> void ObjIntConsumer<T>, ObjLongConsumer<T>, ObjDoubleConsumer<T>
BiFunction<T,U,R>
(T,U) -> R ToIntBiFunction<T,U>, ToLongBiFunction<T,U>, ToDoubleBiFunction<T,U>
就是说任何可以接受一个FI实例的地方,都可以用Lambda表达