1. 简介

lambda表达式可以这样定义(不精确,自己的理解):一段带有输入参数的可执行语句块。

//这里省略list的构造
List<String> names = ...;
Collections.sort(names, (o1, o2) -> o1.compareTo(o2));
//这里省略list的构造
List<String> names = ...;
Collections.sort(names, new Comparator<String>() {@Overridepublic int compare(String o1, String o2) {return o1.compareTo(o2);}
});

上面两段代码分别是:使用lambda表达式来排序和使用匿名内部类来排序。这个例子可以很明显的看出lambda表达式简化代码的效果。接下来展示lambda表达式和其好基友Stream的配合。

List<String> names = new ArrayList<>();
names.add("TaoBao");
names.add("ZhiFuBao");
List<String> lowercaseNames = names.stream().map((String name) -> {return name.toLowerCase();}).collect(Collectors.toList());

2.Lambda语法详解

我们在此抽象一下lambda表达式的一般语法:

(Type1 param1, Type2 param2, ..., TypeN paramN) -> {
statment1;
statment2;
//.............
return statmentM;
}

从lambda表达式的一般语法可以看出来,还是挺符合上面给出的非精确版本的定义–“一段带有输入参数的可执行语句块”。

下面陆续介绍一下lambda表达式的各种简化版:

2.1 参数类型省略–绝大多数情况,

编译器都可以从上下文环境中推断出lambda表达式的参数类型。这样lambda表达式就变成了:

(param1,param2, ..., paramN) -> {
statment1;
statment2;
//.............
return statmentM;
}

所以我们最开始的例子就变成了(省略了List的创建):

List<String> lowercaseNames = names.stream().map((name) -> {return name.toLowerCase();}).collect(Collectors.toList());

2.2 当lambda表达式的参数个数只有一个,可以省略小括号。lambda表达式简写为:

param1 -> {
statment1;
statment2;
//.............
return statmentM;
}

所以最开始的例子再次简化为:

List<String> lowercaseNames = names.stream().map(name -> {return name.toLowerCase();}).collect(Collectors.toList());

2.3 当lambda表达式只包含一条语句时,

可以省略大括号、return和语句结尾的分号。lambda表达式简化为:

param1 -> statment

所以最开始的例子再次简化为:

List<String> lowercaseNames = names.stream().map(name -> name.toLowerCase()).collect(Collectors.toList());

1.4 使用Method Reference(具体语法后面介绍)

List<String> lowercaseNames = names.stream().map(String::toLowerCase).collect(Collectors.toList());

3. Lambda表达式眼中的外部世界

我们可以这样想:lambda表达式其实是快速创建SAM接口的语法糖,原先的SAM接口都可以访问接口外部变量,lambda表达式肯定也是可以。

String[] array = {"a", "b", "c"};
for(Integer i : Lists.newArrayList(1,2,3)){Stream.of(array).map(item -> Strings.padEnd(item, i, '@')).forEach(System.out::println);
}

上面的这个例子中,map中的lambda表达式访问外部变量Integer i。并且可以访问外部变量是lambda表达式的一个重要特性,这样我们可以看出来lambda表达式的三个重要组成部分:

输入参数

可执行语句

存放外部变量的空间

不过lambda表达式访问外部变量有一个非常重要的限制:变量不可变(只是引用不可变,而不是真正的不可变)。

String[] array = {"a", "b", "c"};
for(int i = 1; i<4; i++){Stream.of(array).map(item -> Strings.padEnd(item, i, '@')).forEach(System.out::println);
}

上面的代码,会报编译错误。因为变量i被lambda表达式引用,所以编译器会隐式的把其当成final来处理(ps:大家可以想象问什么上一个例子不报错,而这个报错。)细心的读者肯定会发现不对啊,以前java的匿名内部类在访问外部变量的时候,外部变量必须用final修饰。Bingo,在java8对这个限制做了优化,可以不用显示使用final修饰,但是编译器隐式当成final来处理。

lambda眼中的this

在lambda中,this不是指向lambda表达式产生的那个SAM对象,而是声明它的外部对象。

4.方法引用(Method reference)和构造器引用(construct reference)

方法引用可以在某些条件成立的情况下,更加简化lambda表达式的声明。方法引用语法格式有以下三种:

objectName::instanceMethod
ClassName::staticMethod
ClassName::instanceMethod

前两种方式类似,等同于把lambda表达式的参数直接当成instanceMethod|staticMethod的参数来调用。比如System.out::println等同于x->System.out.println(x);Math::max等同于(x, y)->Math.max(x,y)。

最后一种方式,等同于把lambda表达式的第一个参数当成instanceMethod的目标对象,其他剩余参数当成该方法的参数。比如String::toLowerCase等同于x->x.toLowerCase()。

构造器引用

构造器引用语法如下:ClassName::new,把lambda表达式的参数当成ClassName构造器的参数 。例如BigDecimal::new等同于x->new BigDecimal(x)。

参考:http://ifeve.com/lambda/

转载于:https://www.cnblogs.com/john8169/p/9780584.html

Java 8 之lambda表达式语法相关推荐

  1. lambda表达式语法_使用类似Lambda的语法作为Java中的表达式进行切换

    lambda表达式语法 从Java 14开始, switch表达式具有其他Lambda式 ( case ... -> labels )语法,它不仅可以用作语句,还可以用作计算为单个值的表达式. ...

  2. java saf_Java 8 Lambda表达式探险

    为什么? 我们为什么需要Lambda表达式 主要有三个原因: > 更加紧凑的代码 比如Java中现有的匿名内部类以及监听器(listeners)和事件处理器(handlers)都显得很冗长 &g ...

  3. java8 lambda python_【学习笔记】java8 Lambda表达式语法及应用

    本文是慕课网大牧莫邪老师的视频教程一课掌握Lambda表达式语法及应用的学习笔记.如果觉得内容对你有用,可以购买老师的课程支持一下,课程价格1元,十分良心了. 1. 课程介绍 2. 为什么引入Lamb ...

  4. java junit 异常_JUnit:使用Java 8和Lambda表达式测试异常

    java junit 异常 在JUnit中,有许多方法可以在测试代码中测试异常,包括try-catch idiom JUnit @Rule和catch-exception库. 从Java 8开始,我们 ...

  5. JUnit:使用Java 8和Lambda表达式测试异常

    在JUnit中,有许多方法可以在测试代码中测试异常,包括try-catch idiom JUnit @Rule和catch-exception库. 从Java 8开始,我们还有另一种处理异常的方法:使 ...

  6. Java 8:Lambda表达式与自动关闭

    如果您通过Neo4j的Java API和Java 6使用了Neo4j的早期版本,则可能具有与以下类似的代码,以确保在事务中进行写操作: public class StylesOfTx {public ...

  7. java基础之lambda表达式

    java基础之lambda表达式 1 什么是lambda表达式 lambda表达式是一个匿名函数,允许将一个函数作为另外一个函数的参数,将函数作为参数传递(可理解为一段传递的代码). 2 为什么要用l ...

  8. java中的lambda表达式学习

    Lambda表达式是给函数式接口(SAM接口)的变量或形参赋值的表达式. Lambda表达式替代了原来使用匿名内部类的对象给函数式接口(SAM接口)的变量或形参赋值的形式. java提供了大量的函数式 ...

  9. 如何开始使用Java中的Lambda表达式

    by Luis Santiago 路易斯·圣地亚哥(Luis Santiago) 如何开始使用Java中的Lambda表达式 (How to start working with Lambda Exp ...

最新文章

  1. 报名 | 第三期医工结合系列研讨会:科研领域的知识产权保护
  2. 计算机视觉与深度学习 | 开源SLAM、视觉里程计综述(SLAM、Visual Odometry)
  3. VTK:PolyData之IsoLines
  4. 机器学习算法的基础知识
  5. Linux基础命令---fold
  6. 【渝粤教育】电大中专沟通技巧答案作业 题库
  7. django框架学习文档_Python四大主流网络编程框架,你知道么?
  8. 德国院士:“工业4.0”概念升级了,包含人工智能和5G
  9. cstring移除指定字符串_从String中移除空白字符的多种方式!?差别竟然这么大!...
  10. C# 3.0入门系列(三)
  11. string获取 倒数 下标_NBA球星福克斯沉迷LOL,排名美服倒数98名!胜率太真实了...
  12. WinEdt LaTex(三)—— 宏包
  13. 北风网VIP6级学习视频地址
  14. c语言tc环境下while多大,求救,wintc环境下,写了程序,调试不出来,先谢谢了...
  15. 【PR】简单一招教你使用蒙版做文字动画
  16. ThreadPoolExecutor-线程池的理解
  17. Pytorch+PyG实现GraphSAGE
  18. js获取指定日期的前一年(需要判断闰年和平年)
  19. c#实现简单的手写板功能
  20. PMO只是PM的工具人?太肤浅了

热门文章

  1. HTML5第一弹:彩虹爆炸图
  2. 性能报告——使用AOP与DYNAMICProxy的orm性能测试
  3. matlab 过度曝光,MATLAB:补偿图像处理中的过度曝光/过饱和度
  4. 简述台式计算机创建家庭组的步骤,如何创建和设置家庭组
  5. 雪花怎么画_平安夜怎么过?画个圣诞妆,你是最迷人嘎,你知道吗
  6. 5-6pooling层
  7. linux中文件大小设置函数,truncate函数和ftruncate修改文件大小-linux
  8. java 展现层框架_spring快速入门例子教程:06展现层
  9. Java 并发编程之 CopyOnWriteArrayList
  10. 向服务器上传文件的命令,上传文件到远程服务器的命令