文章目录
- [303. Java Stream API - 查找元素](#303. Java Stream API - 查找元素)
-
- [✅ `findFirst()` 与 `findAny()` 方法概述](#✅
findFirst()与findAny()方法概述) -
- [🧠 关键点:](#🧠 关键点:)
- [🔢 有序流与无序流](#🔢 有序流与无序流)
-
- [📌 **有序流**](#📌 有序流)
- [📌 **无序流**](#📌 无序流)
- [🎬 示例:处理有序流](#🎬 示例:处理有序流)
- [🔄 `findAny()` 与并行流](#🔄
findAny()与并行流) -
- [📌 `findFirst()` 的代价](#📌
findFirst()的代价) - [📌 为什么使用 `findAny()`?](#📌 为什么使用
findAny()?) - [🎬 示例:并行流中的 `findFirst()` 和 `findAny()`](#🎬 示例:并行流中的
findFirst()和findAny())
- [📌 `findFirst()` 的代价](#📌
- [🔀 有序流与无序流的区别](#🔀 有序流与无序流的区别)
-
- [📌 `unordered()` 方法](#📌
unordered()方法) - [🎬 示例:无序流中的 `findFirst()` 和 `findAny()`](#🎬 示例:无序流中的
findFirst()和findAny()) - [📌 `Set` 的无序性](#📌
Set的无序性)
- [📌 `unordered()` 方法](#📌
- [⚠️ 需要注意的性能问题](#⚠️ 需要注意的性能问题)
-
- [📌 结论](#📌 结论)
- [🧾 总结](#🧾 总结)
- [✅ `findFirst()` 与 `findAny()` 方法概述](#✅
303. Java Stream API - 查找元素
✅ findFirst() 与 findAny() 方法概述
Stream API 提供了两个终止操作来查找流中的元素:
findFirst():返回流中的第一个元素。findAny():返回流中的任意一个元素。
这两个方法都返回一个 Optional 类型 ,如果流为空,它们返回的 Optional 也是空的。
🧠 关键点:
- 如果流为空,返回的 Optional 为空。
- 需要理解流的 顺序性 ,因为它决定了
findFirst()返回的是哪个元素。
🔢 有序流与无序流
📌 有序流
有序流是指流中的元素顺序是有意义的,且由 Stream API 保持。比如:
- 基于
List创建的流通常是有序的。 - 有序流中,可以明确地找到"第一个"、"第二个"或"第三个"元素。
📌 无序流
无序流中的元素顺序没有固定,通常在流处理过程中,顺序可能会丢失或是随机的。例如,Set 中的元素没有顺序性。
🎬 示例:处理有序流
java
Collection<String> strings = List.of("one", "two", "three", "four", "five");
String first = strings.stream()
.filter(s -> s.length() == 3)
.findFirst()
.orElseThrow(); // 获取第一个匹配的元素
System.out.println("第一个匹配的元素: " + first);
输出:
java
第一个匹配的元素: one
在这个例子中,因为流是从 List 创建的,所以是有序流,findFirst() 总是返回列表中的第一个匹配元素。
🔄 findAny() 与并行流
📌 findFirst() 的代价
在并行流中,调用 findFirst() 会带来性能开销,因为它需要确保返回的是流中的第一个元素,即使在并行处理中也要保持顺序。
📌 为什么使用 findAny()?
- 如果你不关心返回流中的第一个元素,而只是需要流中的任意一个元素,那么应该使用
findAny()。 findAny()没有顺序约束,适用于处理并行流时,能提高性能。
🎬 示例:并行流中的 findFirst() 和 findAny()
java
Collection<String> strings = List.of("one", "two", "three", "four", "five");
String result = strings.stream()
.parallel() // 使用并行流
.filter(s -> s.length() == 3)
.findFirst()
.orElseThrow(); // 获取第一个匹配的元素
System.out.println("并行流中的第一个匹配元素: " + result);
在并行流中,findFirst() 仍然返回 第一个匹配元素 ,但是有性能开销。如果你对顺序不关心,可以使用 findAny():
java
String anyResult = strings.stream()
.parallel()
.filter(s -> s.length() == 3)
.findAny()
.orElseThrow(); // 获取任意一个匹配元素
System.out.println("并行流中的任意匹配元素: " + anyResult);
🔀 有序流与无序流的区别
📌 unordered() 方法
调用 unordered() 方法后,流就变为 无序流 。在无序流中,findFirst() 的结果将不再是第一个元素,而是流中的一个随机元素。
🎬 示例:无序流中的 findFirst() 和 findAny()
java
Collection<String> strings = List.of("one", "two", "three", "four", "five");
String first = strings.stream()
.unordered() // 将流标记为无序流
.filter(s -> s.length() == 3)
.findFirst()
.orElseThrow(); // 获取第一个匹配元素
System.out.println("无序流中的第一个匹配元素: " + first);
在此情况下,findFirst() 仍然返回一个匹配的元素,但结果会随机。
📌 Set 的无序性
使用 Set 作为源时,元素本身就是无序的。例如:
java
Collection<String> strings = Set.of("one", "two", "three", "four", "five");
String first = strings.stream()
.filter(s -> s.length() == 3)
.findFirst()
.orElseThrow();
System.out.println("无序集合中的第一个匹配元素: " + first);
⚠️ 需要注意的性能问题
在并行流中,findFirst() 操作需要确保元素顺序,而这可能会导致额外的性能开销。尤其是当流的处理只关注第一个匹配元素时,使用 findAny() 会更合适。
📌 结论
- 有序流 :
findFirst()会返回流中的第一个元素。 - 无序流 :
findFirst()和findAny()都会返回流中的一个随机元素。 - 并行流 :使用
findFirst()时会有性能开销,findAny()可以在不需要顺序时提升性能。
🧾 总结
| 方法 | 适用场景 | 顺序性 | 返回类型 |
|---|---|---|---|
findFirst() |
查找第一个匹配的元素 | 有序流 | Optional<T> |
findAny() |
查找任意一个匹配的元素 | 无序流 | Optional<T> |
parallel() |
使流并行处理 | 无序 | 提升性能 |
unordered() |
使流无序 | 无序流 | 随机结果 |