目录

  • 前言
  • `lambda` 语法
    • 基本语法:
    • 基本语法的具体示例:
  • `lambda` 语法使用
    • 用 `lambda` 表达式实现 `Runnable`
    • `lambda` 表达式实现 `forEach` 遍历集合
      • 实体类
      • 使用语法: `x -> 2 * x` 进行 `forEach` 遍历
      • `forEach` 遍历的语法解析
      • 使用双冒号 `::` 进行 `forEach` 遍历
      • 双冒号`::`(方法引用)的语法解析

前言

在对 Java8 发布的 Lambda 表达式进行一定了解之后,发现 Lambda 最核心的就是结合 Stream API 对集合数据的遍历、提取、过滤、排序等一系列操作的简化,以一种函数式编程的方式,对集合进行操作

lambda 表达式就是函数接口类型的实例

lambda 语法

基本语法:

(parameters) -> expression  或  (parameters) ->{ statements; }

基本语法的具体示例:

// 1. 不需要参数,返回值为 5
() -> 5  // 2. 接收一个参数(数字类型),返回其2倍的值
x -> 2 * x  // 3. 接受2个参数(数字),并返回他们的差值
(x, y) -> x – y  // 4. 接收2个int型整数,返回他们的和
(int x, int y) -> x + y  // 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)
(String s) -> System.out.print(s)

lambda 语法使用

lambda 表达式实现 Runnable

lambda 表达式替换了原来匿名内部类的写法,没有了匿名内部类繁杂的代码实现,而是突出了,真正的处理代码。最好的示例就是实现 Runnable 的线程实现方式了: 用 () -> {}代码块替代了整个匿名类

public class LambdaTest1 {public static void main(String[] args) {// 使用匿名内部类 实现多线程new Thread(new Runnable() {@Overridepublic void run() {System.out.println("匿名内部类 实现多线程");}}).start();// 使用的lambda表达式语法为:() -> 5new Thread(() -> System.out.println("使用lambda表达式")).start();}
}

结果

匿名内部类 实现多线程
使用lambda表达式

lambda 表达式实现 forEach 遍历集合

实体类

public class Person {private String name;private int age;private String sex;public Person(String name, int age, String sex) {this.name = name;this.age = age;this.sex = sex;}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +", sex='" + sex + '\'' +'}';}// set,get 方法省略
}

使用语法: x -> 2 * x 进行 forEach 遍历

public class LambdaTest3 {@NotNullpublic static List<Person> getPersonList() {Person p1 = new Person("liu", 22, "male");Person p2 = new Person("zhao", 21, "male");Person p3 = new Person("li", 18, "female");Person p4 = new Person("wang", 21, "female");List<Person> list = new ArrayList<>();list.add(p1);list.add(p2);list.add(p3);list.add(p4);return list;}public static void main(String[] args) {List<Person> personList = LambdaTest3.getPersonList();// 使用 lambda 表达式 forEach 遍历personList.forEach(person -> System.out.println(person.toString()));}
}结果:
Person{name='liu', age=22, sex='male'}
Person{name='zhao', age=21, sex='male'}
Person{name='li', age=18, sex='female'}
Person{name='wang', age=21, sex='female'}

forEach 遍历的语法解析

personList.forEach(person -> System.out.println(person.toString()));

查看 forEach 的源码,我们发现接收的参数类型为:Consumer<? super T> action

default void forEach(Consumer<? super T> action) {Objects.requireNonNull(action);for (T t : this) {action.accept(t);}
}

因此可推断 lambda 表达式的类型:

Consumer<Person> action = person -> System.out.println(person.toString());

如何理解这句代码呢?先看 java.util.function.Consumer 的源码:

@FunctionalInterface
public interface Consumer<T> {void accept(T t);...(省略default方法)
}

我们发现它是一个函数接口,通俗的话讲:函数接口是指只含有一个抽象方法的接口,在 Java8 中,接口里面可以存在已实现的方法,如:default 默认方法、static 静态方法

注意:@FunctionalInterface 注解的作用,当函数接口中存在两个或两个以上的抽象方法时,编译会报错

所以,我们可以这样理解:person -> System.out.println(person.toString()) 就是实现了 Consumer 接口中 accept 方法的实例,->前面的部分 e 表示 accept 方法的入参,->后面的部分表示 accept 方法的具体实现

注意:

  • 如果方法的实现部分由多行代码组成,就用 {} 括起来
  • 如果方法需要返回值,而且方法体只有一行代码,可以省略 return。如果方法体有多行代码,则不能省略 return

使用双冒号 :: 进行 forEach 遍历

public class LambdaTest3 {@NotNullpublic static List<Person> getPersonList() {Person p1 = new Person("liu", 22, "male");Person p2 = new Person("zhao", 21, "male");Person p3 = new Person("li", 18, "female");Person p4 = new Person("wang", 21, "female");List<Person> list = new ArrayList<>();list.add(p1);list.add(p2);list.add(p3);list.add(p4);return list;}public static void main(String[] args) {List<Person> personList = LambdaTest3.getPersonList();// 使用 lambda 表达式 forEach 遍历Consumer<Person> consumer = e -> e.setAge(e.getAge() + 3);personList.forEach(consumer);personList.forEach(System.out::println);}
}结果:
Person{name='liu', age=25, sex='male'}
Person{name='zhao', age=24, sex='male'}
Person{name='li', age=21, sex='female'}
Person{name='wang', age=24, sex='female'}

双冒号::(方法引用)的语法解析

personList.forEach(System.out::println);

之前说过,lambda 表达式就是函数接口类型的实例,而创建该实例的过程,需要实现函数接口中的抽象方法。因此,可以采用引用的方式,即引用已定义好的方法去实现函数接口中的方法

那么 System.out::println 该如何理解?同样根据上下文推断 lambda 表达式的类型:

Consumer action = System.out::println;

System.out::println 的函数接口类型为 java.util.function.Consumer,即在产生该实例对象时,引用了 System.out 对象中的 println 方法,去实现了 Consumer 接口中的 accept 抽象方法。简而言之,即:引用 println 方法去实现了接口中的抽象方法

方法引用有很多种,下面主要讲述以下几种:

  • 构造方法引用:Class::new
  • 静态方法引用:ClassName::methodName
  • 实例上的实例方法引用:instanceReference::methodName
  • 类型上的实例方法引用:ClassName::methodName

方法引用详情查看

文章未完成,后续更新

lambda表达式学习使用实例相关推荐

  1. java lambda表达式学习笔记

    lambda是函数式编程(FP,functional program),在java8中引入,而C#很早之前就有了.在java中lambda表达式是'->',在C#中是'=>'. 杜甫说:射 ...

  2. [研究笔记]Lambda表达式学习笔记

    最近正好用到,就稍微做一下学习笔记.全部经过自己理解的归纳总结,坚持更新. Lambda表达式强大到和图灵机等价,而且极其简洁.优美,太好玩了! ==== Formal Defination Lamb ...

  3. Python中lambda表达式学习

    lambda只是一个表达式,函数体比def简单很多. lambda的主体是一个表达式,而不是一个代码块.仅仅能在lambda表达式中封装有限的逻辑进去. lambda表达式是起到一个函数速写的作用.允 ...

  4. java中的lambda表达式学习

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

  5. lambda表达式学习(详细理解 ) 重点在最后

    多线程的runable接口,如果你的代码简单就可以用lambda简化 package cn.com.zzn.lambda;public class TestLambda2 {// 静态内部类/* st ...

  6. mybatis-plus lambda表达式学习笔记

    使用mybatis-plus的好处在于可以通过Java代码实现Sql逻辑,不需要像mybatis需要通过xml编写Sql语句操作数据库,实现了零配置和手写Sql的烦恼. mybatis-plus中的l ...

  7. Lambda表达式学习

    项目里面需要经常对一系列同类型集合进行操作,如对集合进行增加元素,删除集合的指定索引的元素等等. 我们可以使用ArrayList来进行.如 ArrayList stringArrayList=new ...

  8. lambda表达式学习例子

    https://www.cnblogs.com/franson-2016/p/5593080.html 实例 表达式 说明   将仓库数据,以id为key,仓库数据为value Map<Long ...

  9. 学习Kotlin(五)函数与Lambda表达式

    推荐阅读: 学习Kotlin(一)为什么使用Kotlin 学习Kotlin(二)基本语法 学习Kotlin(三)类和接口 学习Kotlin(四)对象与泛型 学习Kotlin(五)函数与Lambda表达 ...

  10. java里函数式表达式_Java8函数式编程 (一) 数据流和lambda表达式

    JDK 1.8中引入了函数式编程(functional programming,FP),如果您已习惯OOP,一定会感到困惑:什么是函数式编程?这样的编程模式有什么好处? 本文将通过简单的实例令读者对函 ...

最新文章

  1. 未来网络经济的99个趋势报告
  2. 集成IDE anaconda
  3. v-on绑定特性命名带小横杠 ‘-’与props属性中变量怎么对应
  4. java队列实现限流,java中应对高并发的两种策略
  5. [Contest20180418]物理竞赛
  6. 打开应用中SQLite文件的方法
  7. 查询mysql当前连接并删除_查看mysql已有用户并删除
  8. 课程设计—通讯录管理系统
  9. 模式识别算法中英文对照
  10. 江苏海洋大学c语言期末考试题库,海南热带海洋学院18级C语言期末考试PAT编程题...
  11. linux下mysql定时备份
  12. Android WebView调用摄像头录像拍照处理
  13. android水下气泡,科学网—水下爆炸气泡的基本现象及规律 - 黄超的博文
  14. Java HotSpot(TM) 64-Bit Server VM warning:
  15. 深度学习-感受野与有效感受野
  16. 【架构思维】:设计服务降级的思路与方法
  17. 妇产科护理学名词解释
  18. 今天我的app上线了庆祝一下
  19. SpringMVC学习----请求与响应
  20. html th中加斜杠,vue element 表头添加斜线

热门文章

  1. Java中的【锁】事 - 极客大学架构师训练营 架构师 Albert 分享
  2. 用大数据挑选出国外最值得看的前50条swift教程(v.2019)
  3. 字符流中第一个只出现一次的字符
  4. 机器学习中性能评估指标中的准确率(Accuracy)、召回率(Recall=TPR)、精确率(Precision)、误报率(FPR)、漏报率(FNR)及其关系
  5. vscode php断点调试,如何使用vscode断点调试laravel
  6. hadoop配置集群的心得
  7. 2018_08_10_生活记录_关于我和这个博客的说明
  8. 强化学习各概念整理(value/policy-based、on/off-policy、model-based/free、offline)
  9. MATLAB 均值估计函数normfit
  10. LaTeX 报错 Underfull \hbox (badness 10000)