函数式编程

一、什么是函数式编程

    函数式编程是一种编程范式,以函数作为第一对象。注重描述而非具体执行步骤(比如SQL只声明需要什么数据,具体数据库怎么查没指定)

二、特性

高阶函数是指将一个或多个函数装入一个另一个函数中,这个函数会有相关操作并且返回一个全新的函数

三、应用场景

比如创建线程只关心run()方法,但是JAVA8之前还是需要new Thread()和new Runnable()


四、Lambda表达式

方法最重要的是方法签名,那么可以有一个表达式——方法1 = (参数,返回值) {干什么},Lambda表达式就是将返回值隐去之后得出的一个函数式

思考:a -> b -> c -> "d" 代表什么?

a的返回值是一个函数(b -> c ->  "d" )

b的返回值还是一个函数( c ->  "d")

最后就是一个lambda表达式 c ->  "d"

它的意思是将a的入参传递给b函数,b函数将a入参再传给c,c函数传入入参执行"d"操作返回最终结果值

输入Integer返回一个Function<Integer,String>,再将x+Integer作为String类型返回,比如传入1,返回x1

4.1)引入lambda表达式后带来的问题

4.2)函数式接口 SAM(Single Abstract Method)

4.3)内置常用函数式接口

Supplier相当于构造函数只有返回没有参数,Consumer有点像js中onClick(evt)方法只需要一个事件作为参数而不需要返回,Predicate用于if语句,UnaryOperator(高阶函数)指传入一个函数返回一个新的函数
自定义三个参数一个返回值的函数式接口

4.4)函数的调用

可连续调用指第一个apply()方法返回的是一个Function<>,第二个apply()方法返回的是一个Consumer<>,第三个accept()方法返回的是一个Supplier<>

ff(String){

}

ff只是方法签名中的方法名,既不是一种类型,也不是一个表达式

所以Function f = ff?这种编写方式不可以,那如何将方法名ff进行使用呢

JAVA8提供了方法引用

4.5)方法引用    

指定实例方法
指定类型任意实例方法引用—— 比较特殊且难懂

五、函数接口转换

特性中的高阶函数
定义转换的代码编写
转换后使用的代码编写

六、CPS (continuation-passing style)

正常同步方法:

result1 = f1(String a); //方法f1执行返回结果result1

void f2(result1); //方法f2传入result1继续下一步逻辑...

CPS常见的就是callback方法:

void f1(String a, Consumer<Object> callback); //f1()方法没有返回值,但是传入参数a执行后返回的结果会继续传递给Object执行下一个函数callback

先加后乘

七、Stream

7.1)概述

流既然可以是无限的,那在操作StreamB变成StreamA的时候不代表系统已经完全将StreamB中的元素按照我们lambda表达式的规则转换好了放到StreamA中,完全可能延迟处理
Source指获得Stream实例;Intermediate是对Stream所做的操作,可以有多个不同操作组装最重要是filter和map/flatMAP;Terminal是获得结果的操作
reduce是折叠操作

7.2)理解Stream.reduce()

每次累计完之后acc会更新
理论上reduce可以替代一切for循环

7.3)reduce实战    

求和
将当前对比的最大值作为累计值传给下一个元素进行对比
在map映射中已经将Integer转换成了String
分段式处理具体操作在第二个入参中进行描述
多个线程分段处理完后进行一个累计值操作(累计也看作reduce)就叫combiner
用reduce实现map
用reduce实现filter
toListAccumulator()方法返回的就是一个高阶函数

函数式编程的好处,比如方法不想抛异常:

f1 throw SQLException();

f1WithoutThrowExce(){

    try{

        f1();    

    }

}

假如来了一个f2,需要重新写一个 f2WithoutThrowExce();有了函数式编程之后可无限复用

fnWithoutThrowExce(Function<T, R> fn){

    return arg -> {

        try{

            fn.apply(arg);

        }

    }

}

7.4)理解Stream.collect()

reduce不应该用来做toList()操作
第一种
第二个参数使用了 指定类型任意实例方法引用的少一个参数的特性,将第一个入参新建的ArrayList进行了使用;第三个参数如下图将分段的所有Container折叠成一个
可分段处理可不分段处理
第二种

Collector接口

Collector接口可以将本接口的四个函数组装在一起

Collectors工具类

toList
groupBy

7.5)collect实战

collectingAndThen()方法是先聚集然后进行下一步操作

八、进阶

8.1)函数组合

8.2)Optional

最重要的功能,Optional可以安全的一直map()下去,而不用担心变成空盒子的问题
通过一个Person对象获得借记卡银行名字的操作

8.3)flatMap()

盒子中嵌套了盒子,使用flatMap()
扁平一层就是flatmap,Stream也有flatMap()处理Stream<Stream>

8.4)Functor & Monad

IO feichen函数是啥?
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容