好程序员分享java8新特性之Lambda表达式
好程序员分享java8新特性之Lambda表达式
⼀、Lambda表达式简介
什么是Lambda?
Lambda表达式是Java 8推出的⼀个新特性。从本质上讲,Lambda表达式是⼀个匿名函数。
为什么要使⽤Lambda?
使⽤Lambda表达式可以对⼀个接⼝进⾏⾮常简洁的实现。
之前我们在给⼀个接⼝引⽤赋值的时候,可以使⽤接⼝实现类,或者匿名内部类。但是有了
Lambda表达式,我们可以更加⽅便的实现这个需求。
interface Comparator {
int compare(T o1, T o2);
}
class Program {
public static void main(String[] args) {
// 1. 使⽤接⼝实现类实现
class Impl implements Comparator {
@Override
public int compare(Integer o1, Integer o2) {
return o1 - o2;
}
}
Comparator c1 = new Impl();
// 2. 使⽤匿名内部类实现
Comparator c2 = new Comparator() {
@Override
public int compare(Integer o1, Integer o2) {
return o1 - o2;
}
};
// 3. 使⽤Lambda表达式实现
Comparator c3 = (o1, o2) -> o1 - o2;
}
}
从上述例⼦中,我们可以看到: 对同样⼀个接⼝引⽤的实现,Lambda最简单!
Lambda对接⼝的要求?虽然Lambda表达式可以很便捷的实现接⼝,但并不是所有的接⼝都可以使⽤Lambda表达式来实现。
可以⽤Lambda表达式来简洁实现的接⼝是有要求的。因为Lambda表达式本质上来讲,就是⼀个匿名
函数,⽤这个匿名函数来实现接⼝中的⽅法。所以,如果接⼝中有多个必须要实现抽象⽅法时,
Lambda表达式将⽆法是⽤。
注:Lambda表达式要求接⼝中只有⼀个必须要实现的抽象⽅法。但是JAVA 8对接⼝也有⼀个
拓展。现在,我们可以在接⼝中,是⽤default来修饰⼀个⽅法,此时,这个⽅法需要有实
现。那么,实现类在实现接⼝的时候,对于default⽅法,可以实现,也可以不实现。所以,
这⾥所说的接⼝中只有⼀个必须实现的抽象⽅法,与default⽅法⽆关。
@FunctionalInterface**
@FunctionalInterface
因为Lambda表达式要求接⼝中有且只能有⼀个必须实现的抽象⽅法,所以,对接⼝可以使⽤
@FunctionalInterface接⼝来进⾏限定。这个注解约束了接⼝中只能有⼀个必须实现的抽象⽅
法。使⽤这个注解修饰的接⼝,⼜叫做函数式接⼝。
⼆、Lambda表达式基础语法
Lambda表达式,本质上就是⼀个匿名⽅法,所以离不开⽅法的⼏个必要的组成部分:返回值、⽅法
名、参数、⽅法体。但是由于他是⼀个匿名⽅法,所以⽅法名可以忽略。同时,Lambda中也不需要
显式声明返回值类型。所以,我们在写Lambda表达式的时候,只需要关⼼参数和⽅法体即可。
参数: 以()包围起来,多个参数以逗号分隔
(int a, int b)
⽅法体: 以{}包围起来
{ System.out.println("hello world"); }
->: Lambda运算符,⽤来分隔参数和⽅法体
(int a, int b) -> {};
有了这⼏个组成部分,我们就可以对任意的函数式接⼝使⽤Lambda进⾏实现
// ⽆参、⽆返回值
() -> { System.out.println("hello world"); };
// int, int参数、⽆返回值
(int a, int b) -> { System.out.println(a + b); };
// int, int参数、int返回值
(int a, int b) -> { return a + b; };
三、Lambda表达式语法精简
接⼝中定义的⽅法,已经声明了⽅法的参数类型、数量和返回值类型。所以,使⽤Lambda表达式在
实现的时候,对应的部分可以省略参数精简
- 参数的类型可以精简
(int a, int b) -> { System.out.println(a + b); }
可以精简为:
(a, b) -> { System.out.println(a + b); }
- 如果参数数量只有⼀个,⼩括号可以精简
(int a) -> { System.out.println(a); }
可以精简为:
a -> { System.out.println(a); }
⽅法体精简
- 如果⽅法体中只有⼀条语句,则⼩括号可以省略
a -> { System.out.println(a); }
可以精简为:
a -> System.out.println(a);
- 如果⽅法体中唯⼀的⼀条语句是返回值,在精简掉⼤括号后,return也必须省略
a -> { return a * 2; }
可以精简为:
a -> a * 2;
四、Lambda表达式语法进阶之⽅法引⽤
什么是⽅法引⽤
如果在使⽤Lambda进⾏接⼝实现的时候,需要实现的逻辑已经在某⼀个⽅法中实现,则可以直接使
⽤⽅法引⽤,指向指定的⽅法。
interface Calculate {
int calculate(int a, int b);
}
public class Program {
public static void main(String[] args) {
// 接⼝引⽤
Calculate c = (a, b) -> a + b;
}
public static int add(int a, int b) {
return a + b;
}
}在上述代码中,main函数中Calculate引⽤c的实现部分,下⾯已经有⼀个⽅法 add 进⾏了实现。
所以此时,我们不需要再实现⼀次,只需要直接指向已经写好的实现即可。所以,可以进⾏如下改
造:
Calculate c = Program::add;
上⾯的 Program::add 就是⼀个⽅法引⽤。引⽤了Program类中的⼀个静态⽅法add。
在使⽤⽅法引⽤的时候需要注意
- 引⽤的⽅法参数数量、参数类型、返回值类型必须和函数式接⼝中的⽅法定义⼀致。
- ⽅法引⽤必须有引⽤主体,即⽅法的⾪属者。例如:上⽅的add⽅法是⼀个静态⽅法,需要使⽤
类来调⽤。所以⽅法引⽤就是 类::⽅法,如果是⼀个成员⽅法,则需要使⽤ 对象::⽅法 的
形式来引⽤。
构造⽅法的引⽤
如果需要引⽤⼀个构造⽅法,需要使⽤ 类::new 进⾏引⽤
interface CreatePerson {
Person getPerson();
}
class Person {}
class Program {
public static void main(String[] args) {
CreatePerson c = Person::new;
}
}
五、Lambda表达式之综合案例: 排序Comparator
// 排序
list.sort((o1, o2) -> o2.age - o1.age);
// 使⽤Lambda表达式来实现Comparator接⼝,并实例化⼀个TreeSet对象
TreeSet set = new TreeSet<>((o1, o2) -> {
if (o1.age >= o2.age) {
return -1;
}
else {
return 1;
}
});
六、Lambda表达式之综合案例: forEach()// 将集合中的每⼀个元素都带⼊到⽅法accept中。
list.forEach(System.out::println);
// 输出集合中所有的偶数
list.forEach(ele -> {
if (ele % 2 == 0) {
System.out.println(ele);
}
});
七、Lambda表达式之综合案例: removeIf()
// 将集合中的每⼀个元素都带⼊到test⽅法中, 如果返回值是true,则删除这个元素
// 删除集合中的年龄⼤于10岁的元素
list.removeIf(ele -> ele.age > 10);
⼋、Lambda表达式之综合案例: 线程实例化
new Thread(() -> {
for (int i = 0; i < 100; i++) {
System.out.println(i);
}
}).start();
九、系统内置函数式接⼝
系统已经给我们提供了很多函数式接⼝,⽅便我们的使⽤。因此,如果我们需要⽤到以下⽅法的时
候,不需要再设计接⼝,直接使⽤指定的接⼝即可。函数式接⼝
参
数
返回值 特殊说明:⼏个特殊实现的⼦接⼝
Predicate T boolean
IntPredicate :参数:int,返回值:boolean
LongPredicate :参数:long,返回值:boolean
DoublePredicate :参数:double,返回值:boolean
Consumer T void
IntConsumer :参数:int,返回值:void LongConsumer :
参数:int,返回值:void DoubleConsumer :参数:int,返
回值:void
Function T R
IntFunction :参数:int,返回值:R
IntToDoubleFunction :参数:int,返回值:double
IntToLongFunction :参数:int,返回值:long
LongFunction :参数:long,返回值:R
LongToDoubleFunction :参数:long,返回值:double
LongToIntFunction :参数:long,返回值:int
DoubleFunction :参数:double,返回值:R
DoubleToIntFunction :参数:double,返回值:int
DoubleToLongFunction :参数:double,返回值:long
Supplier ⽆ T
BooleanSupplier :参数:⽆,返回值:boolean
IntSupplier :参数:⽆,返回值:int LongSupplier :参
数:⽆,返回值:long DoubleSupplier :参数:⽆,返回值:
double
UnaryOperator T T
IntUnaryOperator :参数:int,返回值:int
LongUnaryOperator :参数:long,返回值:long
DoubleUnaryOperator :参数:double,返回值:double
BinaryOperator T,
T T
IntBinaryOperator :参数:int, int,返回值:int
LongBinaryOperator :参数:long, long,返回值:long
DoubleBinaryOperator :参数:double, double,返回值:
double
BiPredicate
R>
L,
R boolean
BiConsumer
U>
T,
U void
BiFunction
U, R>
T,
U R
上述接⼝中,最常⽤的是 Predicate、Consumer、

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
-
上一篇
好程序员web前端学习路线分享模拟JavaScript中面向对象技术
好程序员web前端学习路线分享模拟JavaScript中面向对象技术,在C#和Java语言中,面向对象是以类的方式实现的,特别是继承这个特性,类的方式继承表现出了强大的功能,而且也易于学习。JavaScript不是纯的面向对象的语言,而是基于对象的语言,对象的继承是以原型函数的形式继承的,很多初学者刚开始接触的时候不太理解,但是JavaScript这种以原型函数的形式实现面向对象技术,不仅是可行的,而且还为面向对象技术提供了动态继承的功能,本文主要讨论了JavaScript的面向对象技术。一、原型对象概述每个JavaScript对象都有原型对象,对象都继承原型对象的所有属性。一个对象的原型是由创建该对象的构造函数定义的。JavaScript的所有函数都有一个名为prototype的属性,该属性引用了原型对象,该原型对象初始化的时候只有constructor属性来引用创建该原型对象的对象。JavaScript没有Class定义类的概念,构造函数就定义了类,并初始化类中的属性,每个类的成员都会从原型对象中继承相同的属性,也就是说,原型对象提供了类的实例共享的属性和方法,这就节约了内存。当读...
-
下一篇
Generator函数
1.为什么要用它? 要用一种工具,它必须有它的价值,首先说一说它的特点。函数的类型目前有四种:普通函数、箭头函数、异步函数、还有Generator函数。Generator的作用是,改善回调地狱,将异步嵌套写成同步写法。 (1)函数定义上的区别: Generator函数是一个普通的函数,但是他也有自己的特点:1)在function关键字和函数名之间有一个*(星号)号,这个星号可以跟在function右上角,也可以跟在函数名左上角,都可以;2)内部使用yield关键字,用来chn内部不同的状态产出。 (2)返回值的区别: Generator是一个普通函数,调用也是在后面加圆括号,但是与普通函数比,区别在于,普通函数会立即执行并产出一个结果,但是Generator不是,它一定会返回一个对象,一个指针对象,也就是iterator Object.要想指针往下移动,需要调用next()方法,函数中的yield相当于暂停,遇到下一个yield或者return就会暂停,使用next可恢复执行,调用next方法,当流程尚未结束时,会返回一个对象,这个对象的value值,就时yield表达式的值,如果结束...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- MySQL数据库在高并发下的优化方案
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- CentOS7,8上快速安装Gitea,搭建Git服务器
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- CentOS8编译安装MySQL8.0.19
- Dcoker安装(在线仓库),最新的服务器搭配容器使用