【Java】23 函数式编程
函数式接口(Functional Interface)是 JDK 1.8 对一类特殊类型的接口的称呼。 这类接口有且仅有一个抽象方法,并且这类接口使用了 @FunctionalInterface 进行注解。
1.1 Lambda 表达式
1.1.1 冗余的代码
当需要启动一个线程去完成任务时,通常会通过java.lang.Runnable
接口来定义任务内容,并使用java.lang.Thread
类来启动该线程。“一切皆对象”作为指导思想,这种做法没毛病:首先创建一个Runnable
接口的匿名内部类对象来指定任务内容,再将其交给一个线程来启动。
public class DemoRunnable {public static void main(String[] args) {// 匿名内部类new Thread(new Runnable() {@Overridepublic void run() { System.out.println("多线程任务执行!");}}).start(); }
}
我认为目前为止,上述代码已经是极简形式,对上述代码进行分析:
♞ Thread
类需要Runnable
接口作为参数,其中的抽象run
方法是用来指定线程任务内容的核心;
♞ 为了指定run
的方法体,需要Runnable
接口的实现类;
♞ 此处为了省去定义一个RunnableImpl
实现类的麻烦,使用匿名内部类;
♞ 重写run
方法,所以方法名称、方法参数、方法返回值再写一遍;
似乎只有方法体才是关键,我们真正希望做的事情是:将run
方法体内的代码传递给Thread
类知晓。
在生活中,当我们需要从武汉到深圳时,可以选择高铁、汽车、骑行甚至是徒步。我们的真正目的是到达深圳,而如何才能到达深圳的形式并不重要,比高铁更好的方式——飞机。那么上述代码有没有更简洁的形式? JDK 1.8 中,加入了Lambda表达式的重量级新特性,为我们打开了新世界的大门。
1.1.2 Lambda 更优写法
public class DemoLambdaRunnable {public static void main(String[] args) {new Thread(() -> System.out.println("多线程任务执行!")).start();}
}
上述代码和 1.1.1 的执行效果是完全一样的,可以在 JDK 1.8 或更高的编译级别下通过。从代码中可以看出:省略了我们不需要的东西,以一种极简的形式执行了线程任务。
1.1.3 Lambda 入门
标准格式
Lambda 省去面向对象的条条框框,格式由 3 部分组成: 一些参数、一个箭头、一段代码,即:(参数类型 参数名称) -> { 代码语句 }
。小括号内的语法与传统方法参数列表一致,无参数则留空;多个参数则用逗号分隔。 ->
是新引入的语法格式,代表指向动作。大括号内的语法与传统方法体要求基本一致。
示例
首先定义一个接口 Add,提供抽象方法 add( )
public interface Add {public abstract int add(int a, int b);
}
然后定义一个方法 show( ),调用抽象方法 add( ) , 最后将使用 λ 表达式构建的 Add 接口子类对象传递给 show 方法。
public class Demo {public static void main(String[] args) {show(2, 3, (int a, int b) -> { return a + b;});}public static void show(int a, int b, Add add) {System.out.println(add.add(a, b));}
}
补充:
使用 λ 表达式必须具有接口,且要求接口中有且仅有一个抽象方法,且可以根据上下文推导相关信息。
λ 表达式小括号内参数的类型可以省略;如果小括号内有且仅有一个参数,则小括号可以省略;如果大括号内有且仅有一个语句,则无论是否有返回值,都可以省略大括号、return关键字及语句分号。
1.2 函数式接口
有且仅有一个抽象方法的接口,称为函数式接口。即:适用于函数式编程场景的接口。而 java 中的函数式编程体现就是 Lambda,所以函数式接口就是可以适用于 Lambda 使用的接口。只有确保接口中有且仅有一个抽象方法,Java 中的 Lambda 才能顺利地进行推导。
1.2.1 自定义函数式接口
/* @FunctionalInterface一旦使用该注解来定义接口,编译器将会强制检查该接口是否确实有且仅有一个抽象方法,否则将会报错。需要注意的是,即使不使用该注解,只要满足函数式接口的定义,这仍然是一个函数式接口,使用起来没有区别。
*/
@FunctionalInterface
public interface MyFunctionInterface {// 有且仅有一个抽象方法的接口public abstract int myMethod();
}
1.2.2 常用函数式接口
☞ 【Java】24 常用函数式接口
1.3 函数式编程
1.3.1 Lambda 的延迟执行
public class Demo {private static void show(int i, String msg) {if (i == 1) {System.out.println(msg);}}public static void main(String[] args) {String msgA = "你好";String msgB = "Hello";String msgC = "Java";show(2, msgA + msgB + msgC);}
}
在调用 show( ) 方法时,无论 show( ) 方法方法体是什么,都会将 msgA + msgB + msgC 拼接为一个字符串传递过去,然而参数可能并不满足 show( ) 方法体执行的条件,拼接好的字符串就成了垃圾,此时就造成了性能浪费。Lambda 表达式完美的解决了这一问题,即:延迟执行,也可以认为不使用,不执行。
如图所示,在不符合条件的情况下,Lambda 表达式将不会执行,从而达到节省性能的效果。实际上使用内部类也可以达到同样的效果,只是将代码操作延迟到了另外一个对象当中通过调用方法来完成。而是否调用其所在方法是在条件判断之后才执行的。
1.3.2 Lambda 作为参数和返回值
Java 中的 Lambda 表达式可以被当作是匿名内部类的替代品。如果方法的参数是一个函数式接口类型,那么就可以使用 Lambda 表达式进行替代。使用 Lambda 表达式作为方法参数,其实就是使用函数式接口作为方法参数。
【Java】23 函数式编程相关推荐
- java8 函数式编程_如何使用Java 8函数式编程生成字母序列
java8 函数式编程 我偶然发现了用户" mip"一个有趣的堆栈溢出问题 . 问题是: 我正在寻找一种生成字母序列的方法: A, B, C, ..., Z, AA, AB, AC ...
- 如何使用Java 8函数式编程生成字母序列
我偶然发现了用户" mip"一个有趣的堆栈溢出问题 . 问题是: 我正在寻找一种生成字母序列的方法: A, B, C, ..., Z, AA, AB, AC, ..., ZZ. 可 ...
- Java 8 函数式编程学习笔记
Java 8 函数式编程学习笔记 @(JAVASE)[java8, 函数式编程, lambda] Java 8 函数式编程学习笔记 参考内容 Java 8中重要的函数接口 扩展函数接口 常用的流操作 ...
- 【Java】函数式编程学习笔记——Stream流
学习视频:https://www.bilibili.com/video/BV1Gh41187uR?p=1 (1)[Java]函数式编程学习笔记--Lambda表达式 (2)[Java]函数式编程学习笔 ...
- 阅读笔记–Java 8函数式编程,建议看书,作者高屋建瓴
阅读笔记–Java 8函数式编程 书籍代码 为什么需要再次修改Java 1996年1月,Java1.0发布,商业发展需要更复杂的应用,跑在功能强大的多核CPU机器上.带有高效运行时编译器的Java虚拟 ...
- Java 代码写的又臭又长,还不会用 Java Stream 函数式编程?
点击上方"猿芯",选择"设为星标" 后台回复"1024",有份惊喜送给面试的你 原文 https://www.cnblogs.com/Car ...
- 深度探秘 Java 8 函数式编程(下)
函数式编程的益处 更精练的代码 函数编程的一大益处,是用更精练的代码表达常用数据处理模式.函数接口能够轻易地实现模板方法模式,只要将不确定的业务逻辑抽象成函数接口,然后传入不同的lambda表达式即可 ...
- Java 8th 函数式编程:lambda 表达式
Lambda 表达式是 java 8th 给我们带来的几个重量级新特性之一,借用 lambda 表达式可以让我们的程序设计更加简洁.最近新的项目摒弃了 6th 版本,全面基于 8th 进行开发,本文将 ...
- 【Java】函数式编程
1 函数式接口 1.1 概念 函数式接口是有且仅有一个抽象方法的接口,可以包括静态和默认方法. @FunctionalInterface:加上注解,检测是否的函数式接口 @FunctionalInte ...
最新文章
- octotree的安装
- Android Launch Mode的学习记录
- 百练OJ:1013:Counterfeit Dollar(假币)
- LILY 英语携手神策数据 数据赋能少儿英语学习创新体验
- Silverlight实用窍门系列:51.Silverlight页面控件的放大缩小、Silverlight和Html控件的互相操作...
- 努力学计算机四年,终于进腾讯了!
- 无数老板做企业还在卖产品赚差价
- Java中hashCode和equals方法的正确使用
- 为什么科学家这么痴迷于研究僵尸?
- bzoj 1257: [CQOI2007]余数之和sum
- C# Cron表达式解析 .net 项目文件
- python双线性插值函数_OpenCV ——双线性插值(Bilinear interpolation)
- CSS——网易云音乐之登录页面的实现
- PyTorch基础:Tensor的组合与分块
- 苹果公司的电脑产品及其历史
- 虚拟机如何进入PE系统
- Spring之AOP 切入点表达式写法
- 用XCA(X Certificate and key management)可视化程序管理SSL 证书(1)--安装XCA
- 基于百度搜索指数生成的可视化地图
- TDOA定位 chan算法和Taylor算法比较仿真 matlab
热门文章
- Mining Hero於ETHDenver峰會提交專案,整合IPFS應用場景
- 模仿美团跑腿做的跑腿小程序
- (附思维导图+笔记)-六面美团后,我发现大厂面试真的有“题库”!
- 栈的push,pop序列
- 乐乐音乐播放器 功能介绍(一)
- 狂野飙车4java的音乐_狂野飙车8音乐名字大全 所有音乐目录敬请下载
- 用docker安装tomcat并实现目录映射端口映射输入ip地址测试网页连接
- 0/0型极限等于多少_有限个极限运算及常见错误小结
- 微信账单怎么查?微信流水账单怎么打印
- 数据分析报告,就该这么写!超详细攻略奉上