0202年了,还没有用上Java函数式编程!!!——Lambda表达式
0202年了,还没有用上Java函数式编程!!!——Lambda表达式
- 函数式编程是什么
- 命令式编程(Imperative)
- 声明式编程(Declarative)
- 函数式编程(Functional)
- 总结
- 函数式编程的好处
- Lambda表达式
- 函数式接口
- 五种形式
- 1.无参数
- 2.有单个参数
- 3.有多个参数
- 4.实现有多行
- 5.带类型
- 方法引用
- 常用内置函数式接口
- Supplier< T >
- Consumer< T >
- Function< T ,R >
- Predicate< T >
- Stream流
- 总结
- 最后
- 参考
函数式编程是什么
这里不得不提的一个点,叫做编程范式,即一类典型的编程风格,那么有哪些比较通用的范式呢
命令式编程(Imperative)
这个其实很好理解,计算机硬件运行指令的方式,就是命令式的,而高级语言中,常用的循环语句,条件语句,就属于这类,即告诉计算机硬件一步一步要去怎样做。
声明式编程(Declarative)
声明式编程是以数据结构的形式来表达程序执行的逻辑,即告诉计算机应该要做什么,常见的形式:SQL(结构化查询语言)
函数式编程(Functional)
函数式编程跟声明式有同样的指导思想,即关注要做什么,但函数式提现函数为第一公民的原则,值得注意的事这里的函数术语指的是一种映射关系,也就是数学中的函数而非计算机中的函数。这里我们可以用一种更简单的方式去对比理解,面向对象编程是对数据进行抽象,而函数式编程是对行为进行抽象。
总结
函数式编程关心数据的映射,命令式编程关心解决问题的步骤。
函数式编程的好处
- 代码简洁,开发快速
- 接近自然语言,易于理解
举例说明之: 有三个"字符串"都说自己比较长,那么到底谁最长?
Stream.of("我长","我才长","你两都没有我长").mapToInt(String::length).summaryStatistics().getMax()
我们来拆分一下(注意方法名的含义)
1. Stream.of(“我长”,“我才长”,“你两都没有我长”):构建了这三个字符组成的流。
2. mapToInt(String::length): 转化每个字符的长度(int类型)。
3. summaryStatistics(): 统计前面的长度数据。
4. getMax(): 获取最大的长度。
简单的一行代码就完成了这个需求,同时轻松易读,何乐而不为之!!!
Lambda表达式
首先我们得明白一点,函数式编程,是可以借助lambda表达式去实现的,所以理解lambda表达式就是一个重点了,而lambda表达式的规则是函数式接口了。
函数式接口
函数式接口:只包含了一个抽象方法的接口。
举个栗子,我们的“精神领袖”——“”窃.格瓦拉“”,就是不打工(对不起!!!)
/*** <Description> “精神领袖”——“窃.格瓦拉”,用于展示函数式接口,不打工是我们唯一的抽象方法 <br>* @author 妖帝艾雷诺 <br>* @version 1.0 <br>* @createDate 2020/04/20 16:42 <br>*/
@FunctionalInterface
public interface CheGuevara {/*** 不打工*/void notWork();}
@FunctionalInterface 注解仅用于标识该接口为函数接口,让编译器能够检查是否符合一个抽象方法。
五种形式
定义了函数式接口后,就要使用了,语法格式如:
(parameters) -> expression 或 (parameters) -> { expression }
1.无参数
实现:
CheGuevara cheGuevara = ()-> System.out.println("这辈子都不可能打工的!!!");
简单理解的话,就是一种语法糖,对比平时我们用的匿名内部类:
CheGuevara cheGuevara = new CheGuevara() {@Overridepublic void notWork() {System.out.println("这辈子都不可能打工的!!!");}};
2.有单个参数
接口:
/*** 不打工 (单参数)* @param electromobile 电瓶车*/void notWork(String electromobile);
实现:
CheGuevara cheGuevara = (electromobile)-> System.out.println("这辈子都不可能打工的!!! 我只想拿【"+electromobile+"】");
3.有多个参数
接口:
/*** 不打工(多参数)* @param electromobile 电瓶车* @param bicycle 自行车*/void notWork(String electromobile, String bicycle);
实现:
CheGuevara cheGuevara = (electromobile, bicycle)-> System.out.println("这辈子都不可能打工的!!! 我想拿【"+electromobile+"】和拿【"+bicycle+"】");
4.实现有多行
接口:
/*** 不打工(多参数)* @param electromobile 电瓶车* @param bicycle 自行车*/void notWork(String electromobile, String bicycle);
实现:
CheGuevara cheGuevara = (electromobile, bicycle)-> {System.out.println("这辈子都不可能打工的!!!");System.out.println("我想拿【"+electromobile+"】");System.out.println("还要拿【"+bicycle+"】");};
5.带类型
通过前面的例子,应该不难发现,参数是没有带有类型的,因为编译器可以通过原先定义的方法判断参数类型,也就是类型推断,有的时候,你想知道具体类型的话,也可以加上,如:
CheGuevara cheGuevara = (String electromobile, String bicycle)-> {System.out.println("这辈子都不可能打工的!!!");System.out.println("我想拿【"+electromobile+"】");System.out.println("还要拿【"+bicycle+"】");};
方法引用
Java8为了使lambda表达式更加精简,提供了方法引用,前提是,lambda表达式只有一行,其语法格式:
类型 | 示例 | 对应lambda表达式 |
---|---|---|
引用静态方法 | 某类名::静态方法 | (a,b,…)-> 某类名.静态方法(a,b,…) |
引用某个对象的实例方法 | 某对象::实例方法 | (a,b,…)-> 某对象.实例方法(a,b,…) |
引用当前参数对象的实例方法(第一个参数) | a::实例方法 | (a,b,…)-> a.实例方法(b,…) |
引用构造方法 | 某类名::new | (a,b,…)-> new 某类名(a,b,…) |
首先方法引用是惰性的,包括前面定义的各种形式,都是惰性的,因为它们仅仅是定义了,并没有真正开始执行,那么怎样才算调用执行,拿上个例子说明:
cheGuevara.notWork("某某牌电动车", "某某牌自行车");
接着,让我们看看方法引用怎么用,还是用多参数的例子,
接口:
/*** 不打工(多参数)* @param electromobile 电瓶车* @param bicycle 自行车*/void notWork(String electromobile, String bicycle);/*** 不打工(Java8接口静态方法,用于展示“方法引用”, 不一定非要在这个接口写实现方法,也可以用其他类)* @param electromobile 电瓶车*/static void staticNotWork(String electromobile, String bicycle){System.out.println("这辈子都不可能打工的!!!我想拿【"+electromobile+"】和拿【"+bicycle+"】");}
实现:
CheGuevara cheGuevara = CheGuevara::staticNotWork;
调用仍然是:
cheGuevara.notWork("某某牌电动车", "某某牌自行车");
留下个问题,大家思考下,我上述例子对应的是方法引用的那种类型呢?
当然,像伟大的IntelliJ IDEA有智能的提示,如果发现你的lambda表达式里能够转化为更精简的方法引用的话。
常用内置函数式接口
我们上述例子,都是围绕自定义的“窃.格瓦拉”函数式接口,难道我们用lambda表达式,就非要自己定义么,当然不是,Java8内置了很多函数式接口,这里举主要的几个(其他的是这几种接口的变式,大同小异,详细可参考菜鸟教程的函数式接口),进行说明。(注意:每个函数式接口仅列举了一个方法,其他的方法使用,建议看源码或者Java8 API)
内置函数式接口 | 描述 |
---|---|
Supplier<T> | 无参数,返回一个T类型结果 |
Consumer<T> | 代表了接受一个输入T类型参数并且无返回的操作 |
Function<T,R> | 接受一个输入T类型参数,返回一个R类型结果 |
Predicate<T> | 接受一个输入T类型参数,返回一个布尔值结果 |
定义一个具体的“窃.格瓦拉”来说明,跟上面其他例子关联不大,仅仅为了延续上面的风格,方便理解。
/*** <Description> 一位看似忠诚的“窃.格瓦拉”的信仰者 <br>** @author 妖帝艾雷诺 <br>* @version 1.0 <br>* @createDate 2020/04/20 23:12 <br>*/
public class CheGuevaraImpl implements CheGuevara{@Overridepublic void notWork(String electromobile, String bicycle) {System.out.println("这辈子都不可能打工的,哪怕你连一百块都不给我!!!但我不拿【"+electromobile+"】也不拿【"+bicycle+"】");}
}
Supplier< T >
//利用Supplier定义一个的"窃.格瓦拉",用方法引用简化new操作Supplier<CheGuevaraImpl> cheGuevaraSupplier = CheGuevaraImpl::new;
Consumer< T >
消费:
//定义一个消费行为,怎么消费的(惰性,还未执行)Consumer<CheGuevaraImpl> cheGuevaraImplConsumer = cheGuevaraImpl1 -> {System.out.println("花了一百块钱,买醉。没钱了!!!");};//接收Supplier提供的一个具体的"窃.格瓦拉",然后作为消费者,进行真实消费 (真正执行)cheGuevaraImplConsumer.accept(cheGuevaraSupplier.get());
消费结果
花了一百块钱,买醉。没钱了!!!
Function< T ,R >
结合上面Consumer<T>的例子,如下:
Function<CheGuevaraImpl, String> cheGuevaraStringFunction = cheGuevaraImpl2->{//输入消费(利用上面定义的消费行为,对当前输入的"窃.格瓦拉"进行接收)cheGuevaraImplConsumer.accept(cheGuevaraImpl2);//输出return "吐了";};//接收Supplier提供的一个具体的"窃.格瓦拉",然后作为消费者,进行真实消费,并输出String output = cheGuevaraStringFunction.apply(cheGuevaraSupplier.get());System.out.println(output);
结果:
花了一百块钱,买醉。没钱了!!!
吐了
Predicate< T >
Predicat常用于判断的场景,比如说,判断当前输入数字是否大于100。(对不起,"窃.格瓦拉"的例子,在这实在编不出来了)
Predicate<Integer> integerPredicate = x-> x > 100;System.out.println("50 > 100 = "+integerPredicate.test(50));
结果:
50 > 100 = false
Stream流
单独写的,请点击链接:
0202年了,还没有用上Java函数式编程!!!——Stream流
总结
- 编程范式:函数式编程是一种编程范式,常见的还有命令式编程,声明式编程,常见的面向对象编程是一种命令式编程。
- 面向对象编程是对数据进行抽象,而函数式编程是对行为进行抽象,现实世界中,数据和行为并存,程序也是如此,因此这两种编程方式我们都得学。
- 函数式编程的核心思想:在思考问题时,使用不可变值和函数,函数对一个值进行处理,映射成另一个值( 函数式编程的一个特点就是可以把函数作为参数传递给另一个函数,也就是所谓的高阶函数)
最后
初次写博客,水平有限,有问题,还望不吝赐教!!!欢迎大家留言讨论,同时欢迎转载,但请注明出处和作者。
所有示例,已经上传至我的github https://github.com/zhiwen-li/Exemplar-learning
参考
- [1] [英] Richard Warburton著,王群锋译.Java8 函数式编程[M].人民邮电出版社:北京,2015.4.
- [2] 李刚.疯狂Java讲义(第4版)[M].电子工业出版社:北京,2018.1.
- [3] backslash112.编程范式:命令式编程(Imperative)、声明式编程(Declarative)和函数式编程(Functional)[EB/OL].https://www.cnblogs.com/sirkevin/p/8283110.html,2018-01-15.
0202年了,还没有用上Java函数式编程!!!——Lambda表达式相关推荐
- 函数式编程 lambda表达式
函数式编程 lambda表达式 从JDK1.8之后为了简化程序的开发,专门提供了lambda表达式的支持,可以简化编程中接口的复杂操作: 范例: 观察以下传统开发中的问题 public interfa ...
- java函数式编程例子_java函数式编程Lambda表达式的示例(一)
函数式编程是时下比较流行的编程方式了,很多新兴的编程语言都对函数式编程有了比较好的支持,她有别于传统的命令式编程,可以将函数(执行代码的过程)作为参数进行传递.JAVA也意识到了函数式编程的重要性,在 ...
- 函数式编程[Lambda 表达式,Optional,Stream流]从入门到精通(一)
文章目录 函数式编程.stream流 1.概述 1.1 学习目的 1.2 函数式编程思想 2.lambda表达式 2.1 概述 2.2 省略规则 3. stream流 3.1 概述 3.2 功能 3. ...
- Java8函数式编程(Lambda表达式,Stream流,Optional)
目录 一.函数式编程思想 二.lambda表达式 1.概念 2.Lambda表达式对接口的要求 编辑编辑编辑 3.Lambda表达式的语法 4.函数引用 4.1引用一个静态方法 4.2引用一个非 ...
- 【怎样写代码】函数式编程 -- Lambda表达式(四):Lambda表达式与Expression树
如果喜欢这里的内容,你能够给我最大的帮助就是转发,告诉你的朋友,鼓励他们一起来学习. If you like the content here, you can give me the greates ...
- 【怎样写代码】函数式编程 -- Lambda表达式(三):LINQ初步
如果喜欢这里的内容,你能够给我最大的帮助就是转发,告诉你的朋友,鼓励他们一起来学习. If you like the content here, you can give me the greates ...
- 【怎样写代码】函数式编程 -- Lambda表达式(二):C#常用委托
如果喜欢这里的内容,你能够给我最大的帮助就是转发,告诉你的朋友,鼓励他们一起来学习. If you like the content here, you can give me the greates ...
- 【怎样写代码】函数式编程 -- Lambda表达式(一):引出
如果喜欢这里的内容,你能够给我最大的帮助就是转发,告诉你的朋友,鼓励他们一起来学习. If you like the content here, you can give me the greates ...
- Java函数式编程和Lambda表达式
文章目录 什么是函数式编程 Lambda表达式 @FunctionalInterface函数式接口 Lambda表达式的格式 方法引用 什么是函数式编程 相信大家都使用过面向对象的编程语言,面向对象编 ...
最新文章
- 【Android 逆向】修改 Android 的 apk 安装包内的文件并重新打包 ( apktool_2.6.0.jar 下载和使用 | zipalign 文件对齐 | apksigner 签名 )
- 谁能想到,我给技术总监“上了一课”?
- mysql 数据类型 int_MySQL数据类型 int(M) 表示什么意思?
- ajax返回值怎么取出来_螺丝断孔里了,怎么取出来?
- iOS之深入解析UmbrellaFramework的封装与应用
- 敏捷开发总结(1)软件研发过程
- Java中使用Socket实现服务器端和客户端通讯
- Linux Qt打包应用程序--利用linuxdeployqt
- 灰度共生矩阵及其数字特征_数字系统及其表示
- linux环境下远程访问ftp
- 算法面试题:均分纸牌
- 被裁员工公开呛声IBM人工智能,有双好鞋却不知怎么走路
- 如何用计算机声卡录声音,录音声卡怎么设置 录音声卡设置教程
- Auto CAD 2022安装教程【64位】
- 牛客 送分啦-QAQ
- 【WIN】超简单的Excel密码破解
- revit二次开发 IdlingExternalEvent 空闲事件与外部事件
- Linux红帽8.2系统中引导过程及引导修复
- Ruby‘s Adventrue游戏制作笔记(十四)Unity播放游戏音效
- python画蝴蝶曲线图
热门文章
- wkhtmltopdf生成pdf时echarts图表不显示的问题
- 服务器设置开机自动登录
- 优酷客户端埋点质量保障三步曲
- 微信小程序富文本图片宽度自适应以及文字自动换行等解决方法
- 【吐血推荐】机器学习/深度学习入门资料汇总及学习建议【入门必看】
- [旅游精选]世界十大城市小吃
- CorelCAD 2019.5 v19.1.1.2035 中文免激活版 Mac 二维制图三维设计软件
- UnityShader入门精要——顶点动画
- 华为OD机试 - 去除多余空格(Java JS Python)
- android甩屏功能,深圳甩屏系统互动优势