什么是Lambda?

Lambda是一个匿名函数,我们可以把Lambda表达式理解为是一段可以传递的代码(将代码像参数一样进行传递,称为行为参数化)。Lambda允许把函数作为一个方法的参数(函数作为参数传递进方法中),要做到这一点就需要了解,什么是函数式接口,这里先不做介绍,等下一篇在讲解。
首先先看一下lambda长什么样?
正常写法:

new Thread(new Runnable() {@Overridepublic void run() {System.out.println("hello lambda");}
}).start();

lambda写法:

new Thread(() -> System.out.println("hello lambda")
).start();

怎么样?是不是感觉很简洁,没错,这就是lambda的魅力,他可以让你写出来的代码更简单、更灵活。

Lambda怎么写?

大家看一些上面的这个图,这就是lambda的语法,一个lambda分为三部分:参数列表、操作符、lambda体。以下是lambda表达式的重要特征:

  • 可选类型声明
    不需要声明参数类型,编译器可以统一识别参数值。也就说(s) -> System.out.println(s)和 (String s) -> System.out.println(s)是一样的编译器会进行类型推断所以不需要添加参数类型。
  • 可选的参数圆括号
    一个参数无需定义圆括号,但多个参数需要定义圆括号。例如:s -> System.out.println(s) 一个参数不需要添加圆括号。
    (x, y) -> Integer.compare(y, x) 两个参数添加了圆括号,否则编译器报错。
  • 可选的大括号
    如果主体包含了一个语句,就不需要使用大括号。

不需要大括号.

 s -> System.out.println(s)

需要大括号

(s) -> {if (s.equals("s")) {System.out.println(s);}};
  • 可选的返回关键字
    如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值。
    Lambda体不加{ }就不用写return:
    Comparator com = (x, y) -> Integer.compare(y, x);
    复制代码Lambda体加上{ }就需要添加return:
  Comparator<Integer> com = (x, y) -> {int compare = Integer.compare(y, x);return compare;};

类型推断

上面我们看到了一个lambda表达式应该怎么写,但lambda中有一个重要特征是可选参数类型声明,就是说不用写参数的类型,那么为什么不用写呢?它是怎么知道的参数类型呢?这就涉及到类型推断了。
java8的泛型类型推断改进:

支持通过方法上下文推断泛型目标类型
支持在方法调用链路中,泛型类型推断传递到最后一个方法

List<Person> ps = ...
Stream<String> names = ps.stream().map(p -> p.getName());

在上面的代码中,ps的类型是List,所以ps.stream()的返回类型是Stream。map()方法接收一个类型为Function<T, R>的函数式接口,这里T的类型即是Stream元素的类型,也就是Person,而R的类型未知。由于在重载解析之后lambda表达式的目标类型仍然未知,我们就需要推导R的类型:通过对lambda表达式lambda进行类型检查,我们发现lambda体返回String,因此R的类型是String,因而map()返回Stream。绝大多数情况下编译器都能解析出正确的类型,但如果碰到无法解析的情况,我们则需要:

使用显式lambda表达式(为参数p提供显式类型)以提供额外的类型信息
把lambda表达式转型为Function<Person, String>
为泛型参数R提供一个实际类型。( map(p -> p.getName()))

方法引用

方法引用是用来直接访问类或者实例已经存在的方法或构造方法,提供了一种引用而不执行方法的方式。是一种更简洁更易懂的Lambda表达式,当Lambda表达式中只是执行一个方法调用时,直接使用方法引用的形式可读性更高一些。
方法引用使用 “ :: ” 操作符来表示,左边是类名或实例名,右边是方法名。
(注意:方法引用::右边的方法名是不需要加()的,例:User::getName)
方法引用的几种形式:

类 :: 静态方法
类 :: 实例方法
对象 :: 实例方法

例如:

Consumer<String> consumer = (s) -> System.out.println(s);

等同于:

Consumer<String> consumer = System.out::println;

例如:

 Function<String, Integer> stringToInteger = (String s) -> Integer.parseInt(s);

等同于:

 Function<String, Integer> stringToInteger = Integer::parseInt;

例如:

BiPredicate<List<String>, String> contains = (list, element) -> list.contains(element);

等同于:

   BiPredicate<List<String>, String> contains = List::contains;

注意:

Lambda体中调用方法的参数列表与返回值类型,要与函数式接口中抽象方法的函数列表和返回值类型保存一致
若Lambda参数列表中的第一个参数是实例方法的调用者,而第二个参数是实例方法的参数时,可以使用ClassName::method

构造器引用
语法格式:类名::new
例如:
Supplier supplier = ()->new User();

等同于:
Supplier supplier = User::new;
复制代码注意:
需要调用的构造器方法与函数式接口中抽象方法的参数列表保持一致。
Lambda是怎么实现的?
研究了半天Lambda怎么写,可是它的原理是什么?我们简单看个例子,看看真相到底是什么:

public class StreamTest {public static void main(String[] args) {printString("hello lambda", (String s) -> System.out.println(s));}public static void printString(String s, Print<String> print) {print.print(s);}
}
@FunctionalInterface
interface Print<T> {public void print(T t);
}

上面的代码自定义了一个函数式接口,定义一个静态方法然后用这个函数式接口来接收参数。编写完这个类以后,我们到终端界面javac进行编译,然后用javap(javap是jdk自带的反解析工具。它的作用就是根据class字节码文件,反解析出当前类对应的code区(汇编指令)、本地变量表、异常表和代码行偏移量映射表、常量池等等信息。)进行解析,如下图:

执行javap -p 命令 ( -p -private 显示所有类和成员)

看上图发现在编译Lambda表达式生成了一个lambda$main$0静态方法,这个静态方法实现了Lambda表达式的逻辑,现在我们知道原来Lambda表达式被编译成了一个静态方法,那么这个静态方式是怎么调用的呢?我们继续进行
执行javap -v -p 命令 ( -v -verbose 输出附加信息)

public com.lxs.stream.StreamTest();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object.""

Java8 Lambda总结相关推荐

  1. Java8 lambda表达式10个示例

    例1.用lambda表达式实现Runnable // Java 8之前: new Thread(new Runnable() {     @Override     public void run() ...

  2. java8 lambda表达式实现自定义用户组件,Don't Repeat Yourself

    2019独角兽企业重金招聘Python工程师标准>>> 一.用户组件的功能 使用java8 lambda表达式实现实现世界的一个例子:用户组件.此用户组件有以下几个操作:获取用户列表 ...

  3. Java8————Lambda表达式(二)

    译者注:文中内容均来自于官方教程<Lambda Expressions>,但是由于英汉语言的差异,部分语句官方描述过于冗余,因此译者根据通常状况的理解做了微调,但不会影响表达的含义.比如: ...

  4. lambda 对象去重_采用java8 lambda表达式 实现 java list 交集 并集 差集 去重复并集...

    采用java8 lambda表达式 实现java list 交集/并集/差集/去重并集 一般的javaList 交.并集采用简单的 removeAll retainAll 等操作,不过这也破坏了原始的 ...

  5. 【Java学习笔记之三十一】详解Java8 lambda表达式

    Java 8 发布日期是2014年3月18日,这次开创性的发布在Java社区引发了不少讨论,并让大家感到激动.特性之一便是随同发布的lambda表达式,它将允许我们将行为传到函数里.在Java 8之前 ...

  6. lambda学习视频和stream学习视频(Java8 Lambda表达式视频教程)-Java爬虫-网络购物的正确打开方式

    百度网盘 链接:https://pan.baidu.com/s/1upU5EVXOQeho6poDYdnhiQ 提取码:088l Java8 Lambda表达式视频教程 https://www.bil ...

  7. Java8 lambda表达式,Comparator.comparing().thenComparing()报错

    环境 Java:1.8+ 前言 今天发了一个问题: 问题描述: 对List进行排序,如果在Comparator.comparing()方法中,只使用一个字段排序,没有问题. 但是如果使用多字段排序,并 ...

  8. 采用java8 lambda表达式 实现 java list 交集 并集 差集 去重复并集

    采用java8 lambda表达式 实现java list 交集/并集/差集/去重并集 一般的javaList 交.并集采用简单的 removeAll retainAll 等操作,不过这也破坏了原始的 ...

  9. Java8 Lambda表达式详解手册及实例

    先贩卖一下焦虑,Java8发于2014年3月18日,距离现在已经快6年了,如果你对Java8的新特性还没有应用,甚至还一无所知,那你真得关注公众号"程序新视界",好好系列的学习一下 ...

  10. java lambda collect_45分钟学会Java8 - Lambda和Stream

    Java11已出,Java8已是主流. 现在来一波操作,应该不会太迟(T_T) 注:本文持续更新 ^_^ 1. 前言 本文主要介绍Java8的2大主要新特性lambda表达式和Stream API,2 ...

最新文章

  1. python多进程详解
  2. 人工智能算法通俗讲解系列(二):逻辑回归
  3. aggr代码 cellranger_单细胞转录组测序数据分析流程-数据预处理
  4. 郁闷的 ConfigurationManager.OpenExeConfiguration
  5. dotnet pack 打包文件版本号引起 Could not load file or assembly 问题
  6. c语言发展过程,C语言发展史
  7. unity ui框架_[教程汇总+持续更新]Unity从入门到入坟——收藏这一篇就够了
  8. emwin读取sd图片_手机内存不够用?这样清理垃圾文件和巧用SD卡扩容硬件存储空间...
  9. 获取最顶层的ViewController top ViewController swift
  10. Django-组件拾遗
  11. Android 友盟分享(截图指定的View分享)
  12. html audio解决浏览器无法播放问题
  13. 我的年终奖发了!你呢???
  14. 【MATLAB统计分析与应用100例】案例011:matlab读取Excel数据,调用regress函数作一元线性回归分析
  15. 关于财务业务模型的思考
  16. 使用WordPress插件搭建一个商城(一)(小白推荐)
  17. 五分钟教你屏蔽百度广告
  18. 淘口令真实url API 返回值说明
  19. Vue3 10多种组件通讯方法
  20. vimdesktop --goreliu 版本配置

热门文章

  1. 【Acwing 219. 剪纸游戏】
  2. Tr A HDU1575
  3. 牛客网【每日一题】4月16日题目精讲 逆序对
  4. CF98E Help Shrek and Donkey(纳什博弈 + 大讨论)
  5. 【背包】逃亡的准备 (ssl 1236)
  6. codeforces 935E Fafa and Ancient Mathematics 语法树、动态规划
  7. Spring 基于注解的配置
  8. 谈谈 Java 的克隆
  9. 关于SimpleDateFormat时间格式化线程安全问题
  10. jmap, jhat, jvisualvm:java堆内存对象分析利器