stream().peek使用
时间: 2025-05-06 12:16:18 浏览: 34
<think>好的,用户想了解Java Stream API中peek方法的用法和示例。我需要先回顾一下peek方法的基本定义和用途。根据引用[1]和[2],peek是一个中间操作,接受一个Consumer参数,用于在流处理过程中执行非侵入式操作,比如调试或监控元素。需要注意peek不会改变流中的元素,这点和map不同。
接下来,用户需要具体的示例。引用[3]提供了一个示例,展示了在过滤前使用peek打印元素。我可以参考这个例子,但可能需要更详细地解释每个步骤的作用。比如,在流处理链中,peek的位置会影响输出,应该说明这一点。
另外,用户可能想知道peek的实际应用场景,比如调试时查看中间结果,或者在修改对象内部状态时的使用。比如,当流元素是可变对象时,peek可以修改其状态,而不会改变引用本身。这点需要举例说明,比如使用一个包含属性的对象,在peek中修改属性值。
还需要注意peek的注意事项,比如在JDK的某些版本中,如果没有终止操作,peek可能不会执行。因此,必须确保流有终止操作,如collect、forEach等。这点引用[4]提到过,需要强调。
用户可能对中间操作和终止操作的区别不太清楚,应该简单说明。比如,中间操作是惰性的,需要终止操作来触发处理流程。
现在,整理结构:先介绍peek的作用,给出基本示例,然后说明调试和监控的用途,再展示修改对象状态的例子,最后总结注意事项。同时,根据用户提供的引用,需要正确标注引用来源,比如引用[1]和[3]。
另外,用户之前的问题可能涉及性能优化或其他方法,但目前专注于peek的用法,所以需要保持回答的针对性。确保示例代码语法正确,使用中文注释,并解释每个步骤的结果。
最后,生成相关问题,帮助用户深入理解,比如与forEach的区别,性能影响,常见错误等。这样能引导用户进一步学习。</think>### Java Stream 的 peek() 方法详解
`peek()` 是 Java Stream API 的**中间操作**,用于对流中的每个元素执行非侵入式操作(如调试、监控或修改对象内部状态),但不会改变流的元素本身。其语法为:
$$Stream<T> \ peek(Consumer<?\ super\ T>\ action)$$
以下通过示例和场景说明其用法。
---
#### 一、基本用法示例
```java
List<String> words = Arrays.asList("apple", "banana", "cherry");
List<String> filtered = words.stream()
.peek(s -> System.out.println("原始值: " + s)) // 打印原始元素
.filter(s -> s.length() > 5) // 过滤长度>5的字符串
.peek(s -> System.out.println("过滤后: " + s)) // 打印过滤后的元素
.collect(Collectors.toList());
```
**输出结果**:
```
原始值: apple
原始值: banana
过滤后: banana
原始值: cherry
过滤后: cherry
```
**说明**:
- `peek()` 在 `filter()` 前/后执行,可观察流的处理过程[^3]
- 最终结果 `filtered` 为 `["banana", "cherry"]`
---
#### 二、主要应用场景
1. **调试流处理逻辑**
查看中间状态,例如转换前后的值:
```java
List<Integer> numbers = Arrays.asList(1, 2, 3);
numbers.stream()
.map(n -> n * 2)
.peek(n -> System.out.println("映射后: " + n))
.collect(Collectors.toList());
```
2. **修改对象内部状态**
若流元素是可变对象,可通过 `peek()` 修改其属性:
```java
class Product {
String name;
double price;
// 省略构造方法和getter/setter
}
List<Product> products = Arrays.asList(
new Product("Laptop", 1000),
new Product("Phone", 500)
);
products.stream()
.peek(p -> p.setPrice(p.getPrice() * 1.1)) // 价格增加10%
.forEach(p -> System.out.println(p.getPrice()));
```
**输出**:
```
1100.0
550.0
```
---
#### 三、注意事项
1. **必须配合终止操作**
`peek()` 作为中间操作,需与 `collect()`, `forEach()` 等终止操作结合使用,否则不会执行[^4]。
2. **与 map() 的区别**
- `map()`:返回新元素,改变流内容
- `peek()`:不改变元素引用,仅执行副作用操作[^2]
3. **性能影响**
频繁使用 `peek()` 可能降低流处理效率,建议仅在调试时使用。
---
阅读全文
相关推荐

















