java8实战读书笔记:复合Lambda表达式

简介: java8实战读书笔记:复合Lambda表达式

本节将重点探讨复合Lambda表达式的使用。在阅读本篇之前建议您先阅读:


java8实战读书笔记:Lambda表达式语法与函数式编程接口,因为本篇是上篇的补充。


本书为博主在学习《java8实战》时的笔记。


image.png

f28d73b7457d91ca7b1b91e6d20bd93c.png

上面是JDK8中java.util.Comparator接口,相比jdk1.7增加了好多方法,也许你会觉得奇怪,为什么接口中还能定义方法,原因是JDK8中,可以为接口添加默认实现,使用default关键字定义。


我们可以这样定义一个比较器:


1Comparator< Apple>  c = Comparator.comparing(Apple::getWeight());

其等价为:

1Comparator< Apple>  c = Comparator.comparing(  (a) -> a.getWeight()  );


为什么可以这样写呢?因为Comparator定义了如下静态方法:

a518899017c781cbd770dde81ffb35fa.jpg


逆序


Comparator定义了一个静态方法,reversed,故我们不需要重新再定义一个比较器,我们可以这样就能实现逆序排序:


1List< Apple> apples = new ArrayList<>();
2apples.sort(  Comparator.comparing(Apple::getWeight()).reversed()  );


比较器链


如果要支持多重排序呢?例如先根据苹果的重量,如果重量相同就按照颜色排序,那如何来实现呢?

1apples.sort(  Comparator.comparing(Apple::getWeight()).thenComparing(  Apple::getColor()  ) );

之所以可以使用上述表达式,是因为Comparator定义了如下方法:

1default <U extends Comparable<? super U>> Comparator<T> thenComparing( Function<? super T, ? extends U> keyExtractor)
2{
3    return thenComparing(comparing(keyExtractor));
4}

温馨提示:Comparator中定义很多thenComparing重载方法,在具体使用过程中,可以先看看其函数声明。


image.png

提到谓词复合,我们就不得不提Predicate<T>函数式编程接口,其类图如下所示:

a6896aebb6d6d32662f2af0bb3e591dc.png

  • and:与
  • negate:非
  • or:或

温馨提示:and 和 or 是按照在表达式链中的位置,从左向右确定优先级的。因此, a.or(b).and(c) 可以看作 (a || b) && c 。


使用示例:从苹果列表中找出所有红色的,并且重量超过150的苹果:


1apples.filter((a -> "red".equals(a.getColor())).and(  a -> a.getWeight() > 150 ));
2a -> "red".equals(a.getColor())  是 (Apple a ) -> "red".equals(a.getColor())的简写。


image.png

函数复合,其对应的函数式编程接口为Function,其类图如下:

81cbe30bb952b0602a77282e521a6e7e.png

  • addThen


andThen 方法会返回一个函数,它先对输入应用一个给定函数,再对输出应用另一个函数。
例如:
Function f = x -> x + 1;
Function g = x -> x * 2;
Function h = f.andThen(g);
int result = h.apply(1);  // 其结果返回4,类似与数学公式  f(g(x))。


  • compose


先把给定的函数用作 compose 的参数里面给的那个函数,然后再把函数本身用于结果。与addThen的函数应用方向相反,同样举例说明如下:


Function f = x -> x + 1;
Function g = x -> x * 2;
Function h = f.compose(g);
int result = h.apply(1);  // 其结果返回3,类似与数学公式  g(f(x))。

相关文章
|
1月前
|
安全 Java 程序员
《从头开始学java,一天一个知识点》之:控制流程:if-else条件语句实战
**你是否也经历过这些崩溃瞬间?** - 看了三天教程,连`i++`和`++i`的区别都说不清 - 面试时被追问&quot;`a==b`和`equals()`的区别&quot;,大脑突然空白 - 写出的代码总是莫名报NPE,却不知道问题出在哪个运算符 这个系列为你打造Java「速效救心丸」!每天1分钟,地铁通勤、午休间隙即可完成学习。直击高频考点和实际开发中的「坑位」,拒绝冗长概念,每篇都有可运行的代码示例。明日预告:《for与while循环的使用场景》。 ---
59 19
|
7天前
|
缓存 监控 Java
深入解析java正则表达式
本文深入解析Java正则表达式的应用,从基础概念到实际开发技巧全面展开。正则表达式是一种强大的文本处理工具,广泛应用于格式验证、搜索替换等场景。Java通过`Pattern`和`Matcher`类支持正则表达式,`Pattern.compile()`方法将正则字符串编译为高效模式对象。文章详细介绍了核心类的功能、常用正则语法及实际案例(如邮箱和电话号码验证)。掌握这些内容,可显著提升文本处理能力,满足多种开发需求。
36 1
|
1月前
|
消息中间件 Java 应用服务中间件
JVM实战—1.Java代码的运行原理
本文介绍了Java代码的运行机制、JVM类加载机制、JVM内存区域及其作用、垃圾回收机制,并汇总了一些常见问题。
JVM实战—1.Java代码的运行原理
|
29天前
|
机器学习/深度学习 人工智能 Java
Java机器学习实战:基于DJL框架的手写数字识别全解析
在人工智能蓬勃发展的今天,Python凭借丰富的生态库(如TensorFlow、PyTorch)成为AI开发的首选语言。但Java作为企业级应用的基石,其在生产环境部署、性能优化和工程化方面的优势不容忽视。DJL(Deep Java Library)的出现完美填补了Java在深度学习领域的空白,它提供了一套统一的API,允许开发者无缝对接主流深度学习框架,将AI模型高效部署到Java生态中。本文将通过手写数字识别的完整流程,深入解析DJL框架的核心机制与应用实践。
71 3
|
7天前
|
Java 编译器 API
Java Lambda 表达式:以 Foo 接口为例深入解析
本文深入解析了 Java 8 中 Lambda 表达式的用法及其背后的函数式接口原理,以 `Foo` 接口为例,展示了如何通过简洁的 Lambda 表达式替代传统匿名类实现。文章从 Lambda 基本语法、函数式接口定义到实际应用层层递进,并探讨默认方法与静态方法的扩展性,最后总结常见误区与关键点,助你高效优化代码!
27 0
|
1月前
|
SQL Rust Java
怎么理解Java中的lambda表达式
Lambda表达式是JDK8引入的新语法,用于简化匿名内部类的代码写法。其格式为`(参数列表) -&gt; { 方法体 }`,适用于函数式接口(仅含一个抽象方法的接口)。通过Lambda表达式,代码更简洁灵活,提升Java的表达能力。
|
1月前
|
SQL IDE 算法
《从头开始学java,一天一个知识点》之:运算符与表达式:算术、比较和逻辑运算
**你是否也经历过这些崩溃瞬间?** - 看了三天教程,连`i++`和`++i`的区别都说不清 - 面试时被追问&quot;`a==b`和`equals()`的区别&quot;,大脑突然空白 - 写出的代码总是莫名报NPE,却不知道问题出在哪个运算符 这个系列为你打造Java「速效救心丸」,每天1分钟,地铁通勤、午休间隙即可完成学习。直击高频考点和实际开发中的「坑位」,拒绝冗长概念,每篇都有可运行的代码示例。明日预告:《控制流程:if-else条件语句实战》。
38 6
|
Java 数据安全/隐私保护 文件存储
《Java EE 7精粹》—— 3.3 复合组件
JSF使用Facelets的功能和资源的处理来定义复合组件,定义在Facelets标记文件中的一个或多个JSF组件组成了一个复合组件。这个.xhtml文件存储在资源库中,可以从页面的任意区域创建一个可重用的组件。
1449 0
|
2月前
|
存储 监控 Java
【Java并发】【线程池】带你从0-1入门线程池
欢迎来到我的技术博客!我是一名热爱编程的开发者,梦想是编写高端CRUD应用。2025年我正在沉淀中,博客更新速度加快,期待与你一起成长。 线程池是一种复用线程资源的机制,通过预先创建一定数量的线程并管理其生命周期,避免频繁创建/销毁线程带来的性能开销。它解决了线程创建成本高、资源耗尽风险、响应速度慢和任务执行缺乏管理等问题。
194 60
【Java并发】【线程池】带你从0-1入门线程池
|
9天前
|
Java 中间件 调度
【源码】【Java并发】从InheritableThreadLocal和TTL源码的角度来看父子线程传递
本文涉及InheritableThreadLocal和TTL,从源码的角度,分别分析它们是怎么实现父子线程传递的。建议先了解ThreadLocal。
47 4
【源码】【Java并发】从InheritableThreadLocal和TTL源码的角度来看父子线程传递