【Java】Stream流、方法引用(二)

简介: 本期主要介绍Stream流、方法引用

1.5 练习:集合元素处理(传统方式)


题目

现在有两个 ArrayList 集合存储队伍当中的多个成员姓名,要求使用传统的 for 循环(或增强 for 循环) 依次 进行以

下若干操作步骤:

1. 第一个队伍只要名字为 3 个字的成员姓名;存储到一个新集合中。

2. 第一个队伍筛选之后只要前 3 个人;存储到一个新集合中。

3. 第二个队伍只要姓张的成员姓名;存储到一个新集合中。

4. 第二个队伍筛选之后不要前 2 个人;存储到一个新集合中。

5. 将两个队伍合并为一个队伍;存储到一个新集合中。

6. 根据姓名创建 Person 对象;存储到一个新集合中。

7. 打印整个队伍的 Person 对象信息。

两个队伍(集合)的代码如下:

image.png

image.png

image.png

解答

既然使用传统的for循环写法,那么:

image.png

运行结果为:

image.png

1.6 练习:集合元素处理(Stream方式)

题目

将上一题当中的传统 for 循环写法更换为 Stream 流式处理方式。两个集合的初始内容不变, Person类的定义也不变

解答

image.png

image.png

第二章 方法引用


在使用Lambda表达式的时候,我们实际上传递进去的代码就是一种解决方案:拿什么参数做什么操作。那么考虑一种情况:如果我们在Lambda中所指定的操作方案,已经有地方存在相同方案,那是否还有必要再写重复逻辑?

2.1 冗余的Lambda场景


来看一个简单的函数式接口以应用Lambda表达式:

image.png

Printable 接口当中唯一的抽象方法 print 接收一个字符串参数,目的就是为了打印显示它。那么通过Lambda来使用它的代码很简单:

image.png

其中 printString 方法只管调用 Printable 接口的 print 方法,而并不管 print 方法的具体实现逻辑会将字符串打印到什么地方去。而 main 方法通过 Lambda 表达式指定了函数式接口 Printable 的具体操作方案为: 拿到

String(类型可推导,所以可省略)数据后,在控制台中输出它

2.2 问题分析


这段代码的问题在于,对字符串进行控制台打印输出的操作方案,明明已经有了现成的实现,那就是 System.out对象中的 println(String) 方法。既然 Lambda 希望做的事情就是调用 println(String) 方法,那何必自己手动调用呢?

2.3 用方法引用改进代码


能否省去Lambda的语法格式(尽管它已经相当简洁)呢?只要引用过去就好了:

image.png

2.4 方法引用符


双冒号 :: 为引用运算符,而它所在的表达式被称为方法引用。如果Lambda要表达的函数方案已经存在于某个方法的实现中,那么则可以通过双冒号来引用该方法作为Lambda的替代者。

语义分析

例如上例中, System.out 对象中有一个重载的 println(String) 方法恰好就是我们所需要的。那么对于

printString 方法的函数式接口参数,对比下面两种写法,完全等效:

Lambda 表达式写法: s - > System.out.println(s) ;

方法引用写法: System.out::println

第一种语义是指:拿到参数之后经 Lambda 之手,继而传递给 System.out.println 方法去处理。

第二种等效写法的语义是指:直接让 System.out 中的 println 方法来取代 Lambda 。两种写法的执行效果完全一样,而第二种方法引用的写法复用了已有方案,更加简洁。

注 :Lambda 中 传递的参数 一定是方法引用中 的那个方法可以接收的类型 , 否则会抛出异常

推导与省略

如果使用Lambda,那么根据可推导就是可省略的原则,无需指定参数类型,也无需指定的重载形式——它们都将被自动推导。而如果使用方法引用,也是同样可以根据上下文进行推导。

函数式接口是 Lambda 的基础,而方法引用是 Lambda 的孪生兄弟。

下面这段代码将会调用 println 方法的不同重载形式,将函数式接口改为 int 类型的参数:

image.png

image.png

2.5 通过对象名引用成员方法


这是最常见的一种用法,与上例相同。如果一个类中已经存在了一个成员方法:

image.png

image.png

image.png

2.6 通过类名称引用静态方法


由于在 java.lang.Math 类中已经存在了静态方法 abs ,所以当我们需要通过 Lambda 来调用该方法时,有两种写法。首先是函数式接口:第一种写法是使用Lambda表达式:

image.png

image.png

在这个例子中,下面两种写法是等效的:

Lambda 表达式: n - > Math.abs(n)

方法引用: Math::abs  

2.7 通过super引用成员方法


如果存在继承关系,当Lambda中需要出现super调用时,也可以使用方法引用进行替代。首先是函数式接口:

image.png

最后是子类 Man 的内容,其中使用了Lambda的写法:

image.png

但是如果使用方法引用来调用父类中的 sayHello 方法会更好,例如另一个子类 Woman

image.png

在这个例子中,下面两种写法是等效的:

Lambda表达式: () -> super.sayHello()

方法引用: super::sayHello

2.8 通过this引用成员方法


this 代表当前对象,如果需要引用的方法就是当前类中的成员方法,那么可以使用 “ this:: 成员方法 ”的格式来使用方法引用。首先是简单的函数式接口:

下面是一个丈夫 Husband 类:

image.png

image.png

开心方法 beHappy 调用了结婚方法 marry ,后者的参数为函数式接口 Richable ,所以需要一个Lambda 表达式。

但是如果这个 Lambda 表达式的内容已经在本类当中存在了,则可以对 Husband 丈夫类进行修改:

image.png

如果希望取消掉Lambda表达式,用方法引用进行替换,则更好的写法为:

image.png

在这个例子中,下面两种写法是等效的:

Lambda 表达式: () - > this.buyHouse()

方法引用: this::buyHouse

2.9 类的构造器引用


由于构造器的名称与类名完全一样,并不固定。所以构造器引用使用 类名称 ::new 的格式表示。首先是一个简单的 Person 类:

image.png

image.png

image.png

在这个例子中,下面两种写法是等效的:

Lambda 表达式: name - > new Person(name)

方法引用: Person::new  

2.10 数组的构造器引用


数组也是 Object 的子类对象,所以同样具有构造器,只是语法稍有不同。如果对应到 Lambda 的使用场景中时,

需要一个函数式接口:

image.png

image.png

在这个例子中,下面两种写法是等效的:

Lambda表达式: length -> new int[length]

方法引用: int[]::new

相关文章
|
3天前
|
存储 JSON Java
《从头开始学java,一天一个知识点》之:方法定义与参数传递机制
**你是否也经历过这些崩溃瞬间?** - 看了三天教程,连`i++`和`++i`的区别都说不清 - 面试时被追问"`a==b`和`equals()`的区别",大脑突然空白 - 写出的代码总是莫名报NPE,却不知道问题出在哪个运算符 🚀 这个系列就是为你打造的Java「速效救心丸」!我们承诺:每天1分钟,地铁通勤、午休间隙即可完成学习;直击痛点,只讲高频考点和实际开发中的「坑位」;拒绝臃肿,没有冗长概念堆砌,每篇都有可运行的代码标本。上篇:《输入与输出:Scanner与System类》 | 下篇剧透:《方法重载与可变参数》。
40 25
|
10天前
|
运维 Java 程序员
Java中的异常处理方法
本文深入剖析Java异常处理机制,介绍可检查异常、运行时异常和错误的区别与处理方式。通过最佳实践方法,如使用合适的异常类型、声明精确异常、try-with-resources语句块、记录异常信息等,帮助开发者提高代码的可靠性、可读性和可维护性。良好的异常处理能保证程序稳定运行,避免资源泄漏和潜在问题。
|
11天前
|
传感器 监控 Java
Java代码结构解析:类、方法、主函数(1分钟解剖室)
### Java代码结构简介 掌握Java代码结构如同拥有程序世界的建筑蓝图,类、方法和主函数构成“黄金三角”。类是独立的容器,承载成员变量和方法;方法实现特定功能,参数控制输入环境;主函数是程序入口。常见错误包括类名与文件名不匹配、忘记static修饰符和花括号未闭合。通过实战案例学习电商系统、游戏角色控制和物联网设备监控,理解类的作用、方法类型和主函数任务,避免典型错误,逐步提升编程能力。 **脑图速记法**:类如太空站,方法即舱段;main是发射台,static不能换;文件名对仗,括号要成双;参数是坐标,void不返航。
34 5
|
1月前
|
存储 安全 算法
Java容器及其常用方法汇总
Java Collections框架提供了丰富的接口和实现类,用于管理和操作集合数据。
Java容器及其常用方法汇总
|
1月前
|
存储 缓存 Java
java语言后台管理ruoyi后台管理框架-登录提示“无效的会话,或者会话已过期,请重新登录。”-扩展知识数据库中密码加密的方法-问题如何解决-以及如何重置若依后台管理框架admin密码-优雅草卓伊凡
java语言后台管理ruoyi后台管理框架-登录提示“无效的会话,或者会话已过期,请重新登录。”-扩展知识数据库中密码加密的方法-问题如何解决-以及如何重置若依后台管理框架admin密码-优雅草卓伊凡
116 3
java语言后台管理ruoyi后台管理框架-登录提示“无效的会话,或者会话已过期,请重新登录。”-扩展知识数据库中密码加密的方法-问题如何解决-以及如何重置若依后台管理框架admin密码-优雅草卓伊凡
|
1月前
|
Java API
java.time常用方法汇总
`java.time` API 是从 Java 8 开始引入的时间日期处理库,旨在替代老旧的 `java.util.Date` 和 `Calendar`。它提供了更简洁、强大和灵活的方式处理日期、时间、时区及时间间隔,支持全球化和时间计算需求。API 包含获取当前时间、创建指定时间、解析和格式化字符串、进行加减运算、比较时间、获取年月日时分秒、计算时间间隔、时区转换以及判断闰年等功能。示例代码展示了如何使用这些功能,极大简化了开发中的时间处理任务。
|
2月前
|
Java
Java快速入门之类、对象、方法
本文简要介绍了Java快速入门中的类、对象和方法。首先,解释了类和对象的概念,类是对象的抽象,对象是类的具体实例。接着,阐述了类的定义和组成,包括属性和行为,并展示了如何创建和使用对象。然后,讨论了成员变量与局部变量的区别,强调了封装的重要性,通过`private`关键字隐藏数据并提供`get/set`方法访问。最后,介绍了构造方法的定义和重载,以及标准类的制作规范,帮助初学者理解如何构建完整的Java类。
|
2月前
|
Java 程序员 调度
Java 高级面试技巧:yield() 与 sleep() 方法的使用场景和区别
本文详细解析了 Java 中 `Thread` 类的 `yield()` 和 `sleep()` 方法,解释了它们的作用、区别及为什么是静态方法。`yield()` 让当前线程释放 CPU 时间片,给其他同等优先级线程运行机会,但不保证暂停;`sleep()` 则让线程进入休眠状态,指定时间后继续执行。两者都是静态方法,因为它们影响线程调度机制而非单一线程行为。这些知识点在面试中常被提及,掌握它们有助于更好地应对多线程编程问题。
87 9
|
2月前
|
安全 Java 程序员
Java面试必问!run() 和 start() 方法到底有啥区别?
在多线程编程中,run和 start方法常常让开发者感到困惑。为什么调用 start 才能启动线程,而直接调用 run只是普通方法调用?这篇文章将通过一个简单的例子,详细解析这两者的区别,帮助你在面试中脱颖而出,理解多线程背后的机制和原理。
78 12
|
2月前
|
算法 Java API
Java 方法注释:规范、实用和高质量的写法
本文深入探讨了如何编写高质量的 Java 方法注释
101 11

热门文章

最新文章