Java8新特性之Lambda
为什么要Lambda
Java8应该是目前最大的一次更新了,更新后我们迎来了很多新特性,其中便包括Lambda表达式,函数式编程的思想正式进入Java,让我们看一个经典案例。
例1 按照两个人的年龄排序的功能
采用匿名内部类已经算简介了,如果专门用一个类去实现Comparator再new出来就更烦了,过去的写法:
// 已经创建好了三个Person实例
List<Person> people = Arrays.asList(person1, person2, person3);
Collections.sort(people, new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
return o1.getAge().compareTo(o2.getAge());
}
});
Lambda版本写法:
Collections.sort(people, (p1, p2) -> p1.getAge().compareTo(p2.getAge()));
还有更简洁的方法引用写法:
Collections.sort(people, Comparator.comparing(Person::getAge));
是不是真的短真的易读,语法糖真的甜!已经9102年了,函数式编程被提到的越来越多,深谙照猫画虎已经行不通了,而且函数式编程和设计模式的碰撞也很多,真的有必要了解下相关概念
哪里用Lambda
行为参数化
函数式编程是一种思想,核心是行为参数化,把一段代码像值一样传递给方法,传入不同的代码实现不同的功能
这是不是很像策略模式以及模板模式?如例1所示,不需要大量的套路代码了,也不需要把代码写到一个类中然后新建实例对象最后把实例对象传递
函数式接口
函数式接口就是只定义一个抽象方法的接口来表示行为,抽象方法不允许抛出受检异常,Java8接口可以有default方法了,函数式接口是允许有default方法的
Lambda表达式看上去确实很有吸引力,我能在任何地方都使用么?答案是不能的,我们只能通过Lambda表达式把代码传到函数式接口中,拿例1中的Comparator接口来看
@FunctionalInterface
public interface Comparator<T> {
int compare(T o1, T o2);
}
Comparator接口只有compare一个抽象方法,Java8特意给它加了注解告诉我们这就是个函数式接口,其实也很好理解,我们没有创建任何实例,只传了一串代码,如果Comparator有两个抽象方法,编译器怎么知道我们实现的是compare方法呢
怎么用Lambda
上面都是说的函数式编程,那么什么是Lambda
Lambda就是匿名的行为参数化的一种语法实现,它没有名称,但它有参数列表、函数主体、返回类型,可能还有一个可以抛出的异常列表
语法
- (parameters) -> expression
- 默认Return的,expression只能是一句代码
- (parameters) -> { statements; }
- 没有默认Retrun,就相当于Comparator.compare( statements; ),statements可以是好多行
tips:如果statements很长,那么我们就不应该用Lambda,而应该单独实现一个方法,然后使用方法引用这样可读性更好,继续例1
// 比如说在MyUtils类下写个方法,故意加长
public static Integer sortPersonByName(Person person1, Person person2) {
Integer age1 = person1.getAge();
Integer age2 = person2.getAge();
return age1.compareTo(age2);
}
// 又用到了方法引用,我们可以把方法引用当作一种便于阅读的语法糖,功能也是传递代码
Collections.sort(people, MyUtils::sortPersonByAge);
凭什么Lambda
在使用Lambda的时候我们没有任何类型声明就能工作这是怎么做到的呢?
函数描述符
函数式接口的抽象方法的签名基本上就是Lambda表达式的签名。我们将这种抽象方法叫作
函数描述符
Comparator.compare的签名
int compare(T o1, T o2);
这个函数式接口的签名就可以描述成需要两个相同类型的变量,然后返回int
( T, T ) -> int
Lambda的签名
(p1, p2) -> p1.getAge().compareTo(p2.getAge())
// 这是易读的写法,我们也可以写成方便说明
(Person p1, Person p2) -> p1.getAge().compareTo(p2.getAge())
可以描述成需要两个Person变量,然后compareTo方法返回int
(Person, Person) -> int
编译器会做类型推断和类型检查,发现两个签名匹配,我们的Lambda表达式就可以顺利执行了
tips:Lambda主体是语句表达式的时候(parameters) -> expression ,尽管expression返回可能不是void,但是也是兼容 T -> void 签名的
进阶
新增函数式接口
除了 Runnable,Comparator等常用函数式接口,为了推动函数式编程,Java8又在 java.util.function 包下为我们提供了大量好用的函数式,因为基本数据类型不能抽象成对象,所以可以看到有大量Double,Int,Long前缀的接口,我们只看比较核心的:
| 接口名 | 抽象方法 | 描述符 |
|---|---|---|
| Predicate | boolean test(T t) | T -> boolean |
| BiPredicate<T, U> | test(T t, U u) | ( T, U ) -> boolean |
| Consumer | void accept(T t) | T -> void |
| BiConsumer<T, U> | void accept(T t, U u) | ( T, U ) -> void |
| Function<T, R> | R apply(T t) | T -> R |
| BiFunction<T, U, R> | R apply(T t, U u) | ( T, U ) -> R |
| Supplier | T get() | void -> T |
tips:Predicate这种对给定内容做判断返回boolean 值,我们叫做谓词
复合Lambda
令人惊喜的是,java8提供的函数式接口还有许多好用的default方法,可以让我们把多个Lambda复合起来,组成流水线。拿用的比较多的Function接口举例,我们要写一封邮件,我们关注的是信的内容
Function<String, String> writeEmailHeader = text -> "Hi ," + "\n" + text;
Function<String, String> writeEmailText = text -> text + "\n";
Function<String, String> writeEmailFooter = text -> text + "BRs" + "\n" + "Chen";
Function<String, String> writeEmail = writeEmailHeader.andThen(writeEmailText).andThen(writeEmailFooter);
System.out.println(writeEmail.apply("I will take half day sick leave today"));
/**
* 输入如下:
* Hi ,
* I will take half day sick leave today
* BRs
* Chen
*/
Java8新特性之Lambda的更多相关文章
- java8新特性: lambda表达式:直接获得某个list/array/对象里面的字段集合
java8新特性: lambda表达式:直接获得某个list/array/对象里面的字段集合 比如,我有一张表: entity Category.java service CategoryServic ...
- Java8 新特性学习 Lambda表达式 和 Stream 用法案例
Java8 新特性学习 Lambda表达式 和 Stream 用法案例 学习参考文章: https://www.cnblogs.com/coprince/p/8692972.html 1.使用lamb ...
- Java8新特性系列-Lambda
转载自:Java8新特性系列-Lambda – 微爱博客 Lambda Expressions in Java 8 Lambda 表达式是 Java 8 最流行的特性.它们将函数式编程概念引入 Jav ...
- Java8新特性之Lambda表达式
lambda表达式是java8给我们带来的几个重量级新特性之一,借用lambda表达式,可以让我们的java程序设计更加简洁.最近新的项目摒弃了1.6的版本,全面基于java8进行开发,本文是java ...
- Java8 新特性之Lambda表达式
1. Lambda 表达式概述 Lambda 是一个匿名函数,我们可以把 Lambda 表达式理解为是一段可以传递的代码(将代码像数据一样进行传递); Lambda 表达式可以写出更简洁,更灵活的代码 ...
- 【Java8新特性】Lambda表达式基础语法,都在这儿了!!
写在前面 前面积极响应读者的需求,写了两篇Java新特性的文章.有小伙伴留言说:感觉Lambda表达式很强大啊!一行代码就能够搞定那么多功能!我想学习下Lambda表达式的语法,可以吗?我的回答是:没 ...
- 零基础学习java------21---------动态代理,java8新特性(lambda, stream,DateApi)
1. 动态代理 在一个方法前后加内容,最简单直观的方法就是直接在代码上加内容(如数据库中的事务),但这样写不够灵活,并且代码可维护性差,所以就需要引入动态代理 1.1 静态代理实现 在讲动态代理之前, ...
- 【Java8新特性】- Lambda表达式
Java8新特性 - Lambda表达式 生命不息,写作不止 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 一个有梦有戏的人 @怒放吧德德 分享学习心得,欢迎指正,大家一起学习成长! ...
- 漫漫人生路-学点Jakarta基础-Java8新特性 Stream/Lambda
背景 Stream 是对集合(Collection)对象功能的增强,它专注于对集合对象进行各种非常便利.高效的聚合操作(aggregate operation),或者大批量数据操作 (bulk dat ...
随机推荐
- 前端利器躬行记(5)——Git
Git是一款开源的分布式版本控制系统,它的出现和Linux紧密相关.Linux内核项目组为了能更好地管理和维护Linux内核开发,于2002年开始启用商业的分布式版本控制系统BitKeeper.虽然软 ...
- FreeSql (二十五)延时加载
FreeSql 支持导航属性延时加载,即当我们需要用到的时候才进行加载(读取),支持1对1.多对1.1对多.多对多关系的导航属性. 当我们希望浏览某条订单信息的时候,才显示其对应的订单详细记录时,我们 ...
- getMeasuredHeight()与getHeight() 以及MeasureSpec.getSize()
getMeasuredHeight()返回的是原始测量高度,与屏幕无关,getHeight()返回的是在屏幕上显示的高度.实际上在当屏幕可以包裹内容的时候,他们的值是相等的,只有当view超出屏幕后, ...
- 【学习笔记】第一章 python安全开发简介
1.1为什么黑客喜欢用python? python为我们提供了非常完善的基础代码库,覆盖了网络.文件.GUI.数据库.文本等大量内容,被形象的称为“”内置电池“”,用python开发,许多功能不必从零 ...
- Fliptile(枚举+DFS)
Problem Description Farmer John knows that an intellectually satisfied cow is a happy cow who will g ...
- MySQL优化之索引原理(二)
一,前言 上一篇内容说到了MySQL存储引擎的相关内容,及数据类型的选择优化.下面再来说说索引的内容,包括对B-Tree和B+Tree两者的区别. 1.1,什么是索引 索引是存储引擎用于快速找 ...
- 【Win10】时钟精确到秒
[Win10]时钟精确到秒 前言 想要桌面右下角的时钟"xx:xx:xx"精确到秒,可以使用绿色免费开源软件Dism++,也可以从该软件的代码中读到方法:用注册表实现. 步骤 进入 ...
- php接受的post数据类型
通常情况下用户使用浏览器网页表单向服务器post提交数据,我们使用PHP的$_POST接收用户POST到服务器的数据,并进行适当的处理.但有些情况下,如用户使用客户端软件向服务端php程序发送post ...
- XSS攻击-原理学习
本文优先发布于简书https://www.jianshu.com/p/04e0f8971890 1.百度百科XSS,跨站脚本攻击(Cross Site Scripting)缩写为CSS,但这会与层叠样 ...
- 利用Python进行数据分析:【NumPy】
一.NumPy:数组计算1.NumPy是高性能科学计算和数据分析的基础包.它是pandas等其他各种工具的基础.2.NumPy的主要功能: # ndarray,一个多维数组结构,高效且节省空间 # 无 ...