如何将一个普通的对象流(如 Stream<T>)转换为数值流,又如何将数值流转换回普通对象流?
在 Java 8 及更高版本中,Stream API 提供了极其便利的方法来在普通对象流(Stream<T>)和数值流(IntStream、LongStream、DoubleStream)之间进行相互转换。
这种转换非常重要,因为数值流(如 IntStream)避免了频繁拆装箱的性能开销,并且提供了诸如 sum()、average()、max() 等便利的数值聚合方法。
以下是具体的转换方法和示例:
一、普通对象流 数值流 (Object Stream to Numerical Stream)
要将 Stream<T> 转换为数值流,可以使用 Stream 接口提供的 mapToInt()、mapToLong() 或 mapToDouble() 方法。这些方法需要传入一个提取数值的函数(Mapper)。
1. 转换方法:
mapToInt(T -> int)得到IntStreammapToLong(T -> long)得到LongStreammapToDouble(T -> double)得到DoubleStream
2. 代码示例:
假设有一个 User 类,包含 age(int)和 salary(double)属性:
java
class User {
private String name;
private int age;
private double salary;
// 构造函数、Getter 省略
public User(String name, int age, double salary) {
this.name = name;
this.age = age;
this.salary = salary;
}
public int getAge() { return age; }
public double getSalary() { return salary; }
}
转换代码:
java
List<User> users = Arrays.asList(
new User("张三", 20, 5000.0),
new User("李四", 25, 8000.0),
new User("王五", 30, 12000.0)
);
// 1. 转换为 IntStream (获取年龄)
IntStream ageStream = users.stream().mapToInt(User::getAge);
// 2. 转换为 DoubleStream (获取薪水)
DoubleStream salaryStream = users.stream().mapToDouble(User::getSalary);
// 3. 转换为 LongStream (假设将年龄转为 long)
LongStream longAgeStream = users.stream().mapToLong(User::getAge);
二、数值流 普通对象流 (Numerical Stream to Object Stream)
将数值流转回对象流有两种常见场景:
- 转为包装类对象流(如
IntStreamStream<Integer>),使用boxed()。 - 转为自定义对象流(如
IntStreamStream<User>),使用mapToObj()。
1. 场景 A:转换为包装类流(装箱)
使用 boxed() 方法。这是最简单直接的转换。
IntStreamStream<Integer>LongStreamStream<Long>DoubleStreamStream<Double>
java
IntStream intStream = IntStream.of(1, 2, 3, 4, 5);
// 使用 boxed() 转为 Stream<Integer>
Stream<Integer> integerStream = intStream.boxed();
2. 场景 B:转换为任意自定义对象流
使用 mapToObj(IntFunction<U> mapper) 方法,可以将数值流中的每一个数字映射为一个新的对象。
java
IntStream idStream = IntStream.of(1, 2, 3);
// 将每一个 id (int) 转换为一个 User 对象,得到 Stream<User>
Stream<User> userStream = idStream.mapToObj(id -> new User("用户_" + id, 20 + id, 5000.0));
三、完整对比与总结
| 转换方向 | 源类型 | 目标类型 | 使用的方法 | 核心代码示例 |
|---|---|---|---|---|
| 对象 数值 | Stream<T> |
IntStream |
mapToInt |
stream.mapToInt(User::getAge) |
Stream<T> |
LongStream |
mapToLong |
stream.mapToLong(User::getId) |
|
Stream<T> |
DoubleStream |
mapToDouble |
stream.mapToDouble(User::getSalary) |
|
| 数值 包装类 | IntStream |
Stream<Integer> |
boxed |
intStream.boxed() |
| 数值 自定义 | IntStream |
Stream<T> |
mapToObj |
intStream.mapToObj(i -> new User(i)) |
通过合理地在对象流和数值流之间切换,你既可以享受数值流带来的高效计算性能(如 intStream.sum()),又可以方便地将其还原为业务对象进行后续处理。
右滑查看面试常问