(全文阅读时间大概3分钟)JDK8通过java.util.function包提供了函数式编程(FP,functionalprogramming),Oracle 此举把FP融入了Java这样一种命令式编程语言(imperativeprogramming)中。虽然目前Java中的FP 不是纯粹的FP(pureFP),但它为Java注入了新的编程风格,新的编程思路,新的编程框架。
所谓命令式编程语言包括过程式编程语言(Procedure programming)和面向对象编程语言(Object oriented programming),它们关注如何解决问题,而FP关注如何描述问题,问题描述清楚后,问题也就解决了。使用命令式编程语言,程序的逻辑由一条条语句,一个个方法,对象以及它们之间的调用来完成, 程序流程分支庞杂,测试困难,分支覆盖不全,很容易就导致程序崩溃,异常如果处理不当,也会埋藏隐患。
如果说软件正在“吞噬”着世界,那么函数则正在支配着软件。函数式编程正是函数支配软件的一个体现,它的基本思想利用函数来解决程序逻辑问题,和数学中的函数一样,相同的输入必定对应相同的输出,即函数是无状态的。其数学基础包括𝝺演算(lambda calculus)和范畴论(category theory)等。
归纳起来,FP有以下特点:
1) 函数是“一等公民”(first class citizens )。OOP关注对象方法的调用,而FP关注函数之间的调用,因此习惯OOP的开发者需要改变思维来习惯FP的思想。
2) 状态不变(immutable state )。纯粹的函数都是无状态的,一系列的函数调用即transformation并不会改变初始对象的状态,只是程序运行的状态。
3) 支持高阶函数(higher-order functions ):即一个或多个函数作为函数参数传入,或函数的返回结果是一个函数,满足其中一个条件即为高阶函数。
4) 无副作用(no side effects )。纯粹的函数都是无副作用的,即不依赖global变量,不会修改对象状态。
5) 支持函数组合(function composition ):需要关注函数链条的执行顺序。
6) 惰性求值(Lazy evaluation ):指一系列嵌套的函数的执行被延迟到其值需要的时刻。
下面看下JDK 的具体实现。JDK8 引入的FP 接口主要放在了java.util.function 包,我们选取有代表性的Function 接口介绍。全文对OOP中的方法和FP中的函数不做过多区分,默认读者通过上述FP的特点能够领会。
-
Function接口:

FuntionalInterface注解表明其是一个函数接口,事实上任意一个接口如果只有一个抽象方法,都可作为函数接口使用,不过覆盖Object类的public方法的接口除外。函数R apply(T t) 方法表明Function 接收一个T 类型的入参,返回一个R 类型的对象。可以通过以下方式声明一个Function实例:
-
方法一,通过lambda表达式:

-
方法二:通过类引用(这里CLassName代表了multMethod所在的类名):

-
方法三:通过匿名类返回:

Function中的函数组合:Function接口中包括两个default方法,

compose组合函数先执行before函数,再执行当前函数;相反andThen先执行当前函数,再执行after函数。例如
内层函数innerFun输出类型为Long,外层函数输入类型为Number,也就是说内层函数的输出类型必须为外层函数输入类型的子类,compose的方法签名中before函数的返回值范型为<?
extends T>也说明这一点(范型中extends代表?(wildcard)继承自T,即?的上界(upper bounded)是T),before函数的入参<? super V>,V默认为Object类型(即?的下界(lower bounded)是V),因此入参可以是任意类型。参见范型相关介绍。
-
Consumer接口代表只有一个入参,没有返回的函数。抽象方法:void accept(T t); 表明代码中任何只有一个入参,没有返回的方法都可作为Consumer函数。函数组合方法:
该方法表明Consumer 函数链消费相同的入参,后续函数的入参类型为前序函数入参的父类,即函数链越往后,入参类型越抽象。例如: 
-
Supplier接口只有一个 T get()方法,该接口代表只有一个类型为T的返回值,没有入参,代码中任何只有一个返回值,没有入参的方法都可作为一个Supplier 函数。
-
UnaryOperator接口继承自Funtion接口,接口定义:public interface UnaryOperator<T>extends Function<T, T>,代表一元运算函数,即返回值与入参的类型一致,这个是与Funtion接口的区别。UnaryOperator 与Funtion中都有一个静态identity方法,两者效果一样,返回值即为入参,所不同的就是UnaryOperator返回一个UnaryOperator ,而Funtion中的identity返回一个Funtion。
-
Predicate接口代表逻辑判断函数。抽象方法boolean test(Tt)说明根据入参t,判断其是否满足一定的逻辑条件,返回bool结果。三个default 方法:
分别代表了逻辑与,逻辑非,逻辑或。isEqual用于判断两个对象是否相 等的Predicate 函数。 
另外,java.util.function 下Bi* 接口代表了双元函数,即输入参数为两个;其他包含有具体类型的接口,如:Long* ,ToDouble* ,LongBinaryOperator 等适用于特定的类型,在熟悉了上述Function,Condumer,UnaryOperator,Predicate等接口后,就非常容易理解和运用它们了。