前身 -- 匿名类

何为匿名类?

没有类名,直接通过new关键字创建这个类的实例

比如:Comparator接口

这是一个单抽象方法的接口,这样的接口被称为函数式接口

public interface Comparator<T> {
int compare(T o1, T o2);
}
  • 正常情况下,想使用compare()方法需要创建一个类实现这个接口
public class C implements Comparator<Integer> {

    public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.sort(new C()); // 在这里传入这个实现类
System.out.println(list); // [2,1]
} public int compare(Integer a, Integer b) {
return Integer.compare(b, a); // 返回 b - a 的比较结果
}
}
  • 使用匿名内部类创建实例可以简化
public static void test() {

    Comparator<Integer> c = new Comparator<Integer>() {
public int compare(Integer a, Integer b) {
return Integer.compare(b, a);
}
}; List<Integer> lst = new ArrayList<>();
lst.add(1);
lst.add(2);
lst.sort(c);
System.out.println(lst); // [2,1]
}
  • 再简化
List<Integer> lst = new ArrayList<>();
lst.add(1);
lst.add(2);
// 策略模式,可以学习这种思想,自定义排序
lst.sort(new Comparator<Integer>() {
public int compare(Integer a, Integer b) {
return Integer.compare(b, a);
}
});
System.out.println(lst); // [2,1]

lambda 表达式

前面使用匿名类还是冗长,因此又创建了更简洁的方式来实现接口

List<Integer> lst = new ArrayList<>();
lst.add(1);
lst.add(2);
lst.sort((Integer a, Integer b) -> {return Integer.compare(b, a);});
System.out.println(lst);

本质是对匿名类的简写,只留下了这个 唯一抽象方法 的 参数列表 和 功能实现逻辑

lambda表达式箭头左侧中的参数列表 对应的是 接口中抽象方法的参数列表,右侧是对抽象方法需要实现的功能

  • 可以再简化
List<Integer> lst = new ArrayList<>();
lst.add(1);
lst.add(2);
lst.sort((a, b) -> Integer.compare(b, a));
System.out.println(lst);

把多余的全去了,只留下必要的

其实我在好奇,把它简化为这样子,编译器怎么知道它是个Comparator<? super E>这样的类型呢?

根据GPT的解答:

Java 编译器会根据上下文推断出该 Lambda 表达式的类型。因为 sort 方法期望一个 Comparator 对象作为参数,所以编译器会推断出这个 Lambda 表达式的类型是 Comparator 类型

额,总结一下就是,因为sort需要一个这样类型的参数,所以我就推断它就是一个这样的参数

方法引用

方法引用可以看出是lambda表达式的另外一种表现形式,也可以看成是对lambda的再次简化,思想类似于借花献佛、借鸡下蛋、草船借箭、借刀杀人....

怎么实现的呢?

如果有一个类/实例的方法和我这个lambda表达式中要实现的功能逻辑是一样的,那我能不能直接借用呢?

直接借用的话,至少需要知道这个类/实例和对应的方法

有三种实现方式:类名::静态方法,类名::实例方法,对象::实例方法 (其实思想基本一致)

类名::静态方法

首先,我需要根据一个list中元素大小按升序排列可以这么写:lst.sort((a, b) -> b - a);

List<Integer> lst = new ArrayList<>();
lst.add(1);
lst.add(2);
lst.sort((a, b) -> a - b);
System.out.println(lst); // [1,2]

a-b会返回-1、0、1这三种int值的其中一种,这个逻辑在Integer类的compara方法已经有实现了,所以可以直接引用Integer类的compara方法

// Integer.class
public static int compare(int x, int y) {
return (x < y) ? -1 : ((x == y) ? 0 : 1);
}

(前面也有用过,只是那是在功能逻辑中调用 Integer.compare())

List<Integer> lst = new ArrayList<>();
lst.add(1);
lst.add(2);
lst.sort(Integer :: compare);
System.out.println(lst);

类名::实例方法

除了使用compare方法可以实现List排序以外,compareTo方法也可以,它是Integer.class中的一个实例方法,调用的compare

// Integer.class
public int compareTo(Integer anotherInteger) {
return compare(this.value, anotherInteger.value);
}

使用lambda方式:

lst.sort((a, b) -> a.compareTo(b));

使用方法引用方式:

lst.sort(Integer :: compareTo);

对象::实例方法

forEach中接收一个函数式接口Consumer<? super T> action,并调用了这个接口的抽象方法

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

如果使用lambda来打印列表中的元素的话,可以这么写:

List<Integer> lst = new ArrayList<>();
lst.add(1);
lst.add(2);
lst.forEach(a -> System.out.println(a));

这里和上一个例子逻辑一样,既然是在功能逻辑中调用了System.out的println方法,那肯定也能直接引用它们

这里使用System类中静态成员对象out来解释,out是一个PrintStream类型的对象,PrintStream这个类有一个println方法

// System.class
public final static PrintStream out = null;

最终简化为:

List<Integer> lst = new ArrayList<>();
lst.add(1);
lst.add(2);
lst.forEach(System.out::println);

总结

最后浅谈下我的理解

所谓的lambda表达式就是为简化代码而生,专为函数式接口(单个抽象方法的接口)服务

从 最初的匿名类的形式,即new Obj(){...某个方法...}() -> {} 的形式,再到::的形式,格式越来越简单

  • new Obj(){...某个方法...}() -> {} 的形式本质上是抽取了关键部分,因为人家调用方法时只需要直到方法的形参和实现逻辑就可以了,所以去掉了其余部分
  • () -> {} 的形式,再到::这个过程的思想类似于借花献佛,如果这个方法的实现逻辑在某个类里有相同的实现逻辑,那我把这个类和方法借来一用可好?

参考资料

https://zhuanlan.zhihu.com/p/365505945

https://www.bilibili.com/video/BV1ci4y1g7qD?p=7&vd_source=885d19c94243993175e057fd4d9dc13c

原来 Lambda 这么简单的更多相关文章

  1. python lambda表达式简单用法【转】

    python lambda表达式简单用法 1.lambda是什么? 看个例子: g = lambda x:x+1 看一下执行的结果: g(1) >>>2 g(2) >>& ...

  2. python lambda表达式简单用法

    习条件运算时,对于简单的 if else 语句,可以使用三元运算来表示,即: 1 2 3 4 5 6 7 8 # 普通条件语句 if 1 == 1:     name = 'wupeiqi' else ...

  3. Python中的lambda的简单介绍

    在学习python的过程中,lambda的语法经常出现,现在将它整理一下,以备日后查看. 1.lambda是什么? 举个例子如下: func=lambda x:x+1 print(func(1)) p ...

  4. Python Lambda 的简单用法

    下面代码简单举例介绍以下 lambda的用法. from functools import reduce #1 python lambda会创建一个函数对象,但不会把这个函数对象赋给一个标识符,而de ...

  5. Python3基础 lambda表达式 简单示例

    镇场诗: 诚听如来语,顿舍世间名与利.愿做地藏徒,广演是经阎浮提. 愿尽吾所学,成就一良心博客.愿诸后来人,重现智慧清净体.-------------------------------------- ...

  6. C++11 Lambda表达式简单解析

    C++11 新增了非常多特性,lambda 表达式是当中之中的一个.假设你想了解的 C++11 完整特性, 建议去http://www.open-std.org/看看新标准! 非常多语言都提供了 la ...

  7. set、def、lambda、内置函数、文件操作

    set : 无序,不重复,可以嵌套 .add (添加元素) .update(接收可迭代对象)---等于批量 添加 .diffrents()两个集合不同差 .sysmmetric difference( ...

  8. Java Lambda简明教程(一)

    Lambda表达式背景 许多热门的编程语言如今都有一个叫做lambda或者闭包的语言特性,包括比较经典的函数式编程语言Lisp,Scheme,也有稍微年轻的语言比如JavaScript,Python, ...

  9. java8 Lambda表达式的新手上车指南(1)

    背景 java9的一再推迟发布,似乎让我们恍然想起离发布java8已经过去了三年之久,java8应该算的上java语言在历代版本中变化最大的一个版本了,最大的新特性应该算得上是增加了lambda表达式 ...

  10. Lambda 表达式,Java中应用Lambda 表达式

    一.Lambda 表达式 简单来说,编程中提到的 lambda 表达式,通常是在需要一个函数,但是又不想费神去命名一个函数的场合下使用,也就是指匿名函数. 链接:知乎 先举一个普通的 Python 例 ...

随机推荐

  1. List去除重复数据的五种方式

    来自:CSDN,作者:多纤果冻 链接:https://blog.csdn.net/qq_37939251/article/details/90713643 以下介绍五种-不同的方法去除 Java 中A ...

  2. Valine评论插件因为LeanCloud国内域名解析问题无法正常使用的解决方法

    近日,LeanCloud 国内域名解析存在问题,Valine评论插件的评论内容都储存在LeanCloud,使用Valine评论插件的个人博客的评论及阅读数会显示失败. 关于 LeanCloud 国内域 ...

  3. 安装mysql5.7.20,和遇到的一些错误及解决方案

    下载: mysql-5.7.20是解压版免安装的,mysql-5.7.20下载地址:http://dev.mysql.com/downloads/mysql/ 2.安装 解压在你喜欢的位置 3.配置 ...

  4. 仅三天,我用 GPT-4 生成了性能全网第一的 Golang Worker Pool,轻松打败 GitHub 万星项目

    目录 1. 我写了一个超牛的开源项目 1.1 你看看这性能 1.2 你看看这功能 1.3 你猜我这一百天都经历了啥 2. 你有多久没写并发程序了? 3. 问:一个 Worker Pool 程序需要包含 ...

  5. 服务端不回应客户端的syn握手,连接建立失败原因排查

    背景 测试环境有一个后台服务,部署在内网服务器A上(无外网地址),给app提供接口.app访问这个后台服务时,ip地址是公网地址,那这个请求是如何到达我们的内网服务器A呢,这块我咨询了网络同事,我画了 ...

  6. Kioptrix Level 1

    Kioptrix这个系列靶机默认是桥接模式,如果我们kali使用NAT是扫描不到靶机的,通过VM的靶机网络设置也不能更改成功. 解决方式:每次下载好靶机先不导入VM,如果已经导入,需要"移除 ...

  7. Ceph-介绍

    Ceph架构简介及使用场景介绍 一.Ceph简介 Ceph是一个统一的分布式存储系统,设计初衷是提供较好的性能.可靠性和可扩展性. 二.Ceph特点 1.高性能 - 采用CRUSH算法,数据分布均衡, ...

  8. Hugging News #0904:🤗 登陆 AWS Marketplace

    每一周,我们的同事都会向社区的成员们发布一些关于 Hugging Face 相关的更新,包括我们的产品和平台更新.社区活动.学习资源和内容更新.开源库和模型更新等,我们将其称之为「Hugging Ne ...

  9. Text2Cypher:大语言模型驱动的图查询生成

    话接上文<图技术在 LLM 下的应用:知识图谱驱动的大语言模型 Llama Index> 同大家简单介绍过 LLM 和图.知识图谱相关的结合,现在我来和大家分享下最新的成果.毕竟,从 GP ...

  10. 织梦dede邮箱发信配置教程

    环境要求 主机465端口是开启和放行的 php扩展openssl是开启的 php扩展sockets是开启的 1.QQ邮箱或者163邮箱.126邮箱,开启SMTP服务,拿到授权码,根据自己的来 QQ邮箱 ...