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流

总结

  1. 编程范式:函数式编程是一种编程范式,常见的还有命令式编程,声明式编程,常见的面向对象编程是一种命令式编程。
  2. 面向对象编程是对数据进行抽象,而函数式编程是对行为进行抽象,现实世界中,数据和行为并存,程序也是如此,因此这两种编程方式我们都得学。
  3. 函数式编程的核心思想:在思考问题时,使用不可变值和函数,函数对一个值进行处理,映射成另一个值( 函数式编程的一个特点就是可以把函数作为参数传递给另一个函数,也就是所谓的高阶函数)

最后

初次写博客,水平有限,有问题,还望不吝赐教!!!欢迎大家留言讨论,同时欢迎转载,但请注明出处和作者。
所有示例,已经上传至我的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表达式相关推荐

  1. 函数式编程 lambda表达式

    函数式编程 lambda表达式 从JDK1.8之后为了简化程序的开发,专门提供了lambda表达式的支持,可以简化编程中接口的复杂操作: 范例: 观察以下传统开发中的问题 public interfa ...

  2. java函数式编程例子_java函数式编程Lambda表达式的示例(一)

    函数式编程是时下比较流行的编程方式了,很多新兴的编程语言都对函数式编程有了比较好的支持,她有别于传统的命令式编程,可以将函数(执行代码的过程)作为参数进行传递.JAVA也意识到了函数式编程的重要性,在 ...

  3. 函数式编程[Lambda 表达式,Optional,Stream流]从入门到精通(一)

    文章目录 函数式编程.stream流 1.概述 1.1 学习目的 1.2 函数式编程思想 2.lambda表达式 2.1 概述 2.2 省略规则 3. stream流 3.1 概述 3.2 功能 3. ...

  4. Java8函数式编程(Lambda表达式,Stream流,Optional)

    目录 一.函数式编程思想 二.lambda表达式 1.概念 2.Lambda表达式对接口的要求 ​编辑​编辑​编辑 3.Lambda表达式的语法 4.函数引用 4.1引用一个静态方法 4.2引用一个非 ...

  5. 【怎样写代码】函数式编程 -- Lambda表达式(四):Lambda表达式与Expression树

    如果喜欢这里的内容,你能够给我最大的帮助就是转发,告诉你的朋友,鼓励他们一起来学习. If you like the content here, you can give me the greates ...

  6. 【怎样写代码】函数式编程 -- Lambda表达式(三):LINQ初步

    如果喜欢这里的内容,你能够给我最大的帮助就是转发,告诉你的朋友,鼓励他们一起来学习. If you like the content here, you can give me the greates ...

  7. 【怎样写代码】函数式编程 -- Lambda表达式(二):C#常用委托

    如果喜欢这里的内容,你能够给我最大的帮助就是转发,告诉你的朋友,鼓励他们一起来学习. If you like the content here, you can give me the greates ...

  8. 【怎样写代码】函数式编程 -- Lambda表达式(一):引出

    如果喜欢这里的内容,你能够给我最大的帮助就是转发,告诉你的朋友,鼓励他们一起来学习. If you like the content here, you can give me the greates ...

  9. Java函数式编程和Lambda表达式

    文章目录 什么是函数式编程 Lambda表达式 @FunctionalInterface函数式接口 Lambda表达式的格式 方法引用 什么是函数式编程 相信大家都使用过面向对象的编程语言,面向对象编 ...

最新文章

  1. 【Android 逆向】修改 Android 的 apk 安装包内的文件并重新打包 ( apktool_2.6.0.jar 下载和使用 | zipalign 文件对齐 | apksigner 签名 )
  2. 谁能想到,我给技术总监“上了一课”?
  3. mysql 数据类型 int_MySQL数据类型 int(M) 表示什么意思?
  4. ajax返回值怎么取出来_螺丝断孔里了,怎么取出来?
  5. iOS之深入解析UmbrellaFramework的封装与应用
  6. 敏捷开发总结(1)软件研发过程
  7. Java中使用Socket实现服务器端和客户端通讯
  8. Linux Qt打包应用程序--利用linuxdeployqt
  9. 灰度共生矩阵及其数字特征_数字系统及其表示
  10. linux环境下远程访问ftp
  11. 算法面试题:均分纸牌
  12. 被裁员工公开呛声IBM人工智能,有双好鞋却不知怎么走路
  13. 如何用计算机声卡录声音,录音声卡怎么设置 录音声卡设置教程
  14. Auto CAD 2022安装教程【64位】
  15. 牛客 送分啦-QAQ
  16. 【WIN】超简单的Excel密码破解
  17. revit二次开发 IdlingExternalEvent 空闲事件与外部事件
  18. Linux红帽8.2系统中引导过程及引导修复
  19. Ruby‘s Adventrue游戏制作笔记(十四)Unity播放游戏音效
  20. python画蝴蝶曲线图

热门文章

  1. wkhtmltopdf生成pdf时echarts图表不显示的问题
  2. 服务器设置开机自动登录
  3. 优酷客户端埋点质量保障三步曲
  4. 微信小程序富文本图片宽度自适应以及文字自动换行等解决方法
  5. 【吐血推荐】机器学习/深度学习入门资料汇总及学习建议【入门必看】
  6. [旅游精选]世界十大城市小吃
  7. CorelCAD 2019.5 v19.1.1.2035 中文免激活版 Mac 二维制图三维设计软件
  8. UnityShader入门精要——顶点动画
  9. 华为OD机试 - 去除多余空格(Java JS Python)
  10. android甩屏功能,深圳甩屏系统互动优势