Java 中的 Stream mapToDouble() 方法及示例

2025年1月7日 | 阅读 6 分钟

在 Java 中,`mapToDouble()` 方法是 Stream 接口的成员之一,该接口在 Java 8 中引入。它通过将给定的 `ToDoubleFunction` 应用于流中的每个元素,将流的元素转换为原始的 `double` 值,从而提供了一种将流元素高效转换为专门的 `DoubleStream` 的方法。

方法签名

DoubleStream:这是 `mapToDouble()` 的返回类型。它是一个专门用于处理原始 `double` 类型值的流。

mapToDouble:这是方法的名称。

ToDoubleFunction<? super T> mapper:这是一个函数式接口,是 Java 的 util 包的一部分,用作各种 Stream 方法的参数。ToDoubleFunction:表示一个产生 `double` 值结果的函数。<? super T>:表示一个通配符(?),代表 T 的任何超类。它确保了接受 T 的实例或 T 的任何超类的元素的灵活性。指定的 mapper 函数(ToDoubleFunction)将应用于流中的每个元素。它根据函数指定将每个元素转换为 `double` 值。

示例 1:将 Integer Stream 转换为 DoubleStream

在此示例中,我们创建了一个包含 1、2、3、4、5 的 Integer 值流。`integerStream.mapToDouble(i -> i * 1.5)` 用于将 `integerStream` 中的每个整数 (i) 转换为 `double` 值。`i -> i * 1.5` 是一个 lambda 表达式,定义了将每个整数乘以 1.5 的转换。结果是一个 `DoubleStream`(`doubleStream`),其中包含转换后的值(1.5、3.0、4.5、6.0、7.5)。

文件名:MapToDoubleExample.java

输出

 
Original Values: [1, 2, 3, 4, 5]
Transformed Values: [1.5, 3.0, 4.5, 6.0, 7.5]   

示例 2:计算 Integer Stream 的平均值

在此示例中,`IntStream.rangeClosed(1, 10)` 创建了一个包含从 1 到 10(含)的整数的 `IntStream`。`filter(i -> i % 2 != 0)` 过滤掉偶数(`i % 2 != 0` 检查 i 是否为奇数),它也确保只考虑奇数来计算平均值。`mapToDouble(i -> i)` 将每个剩余的整数映射为 `double` 值。`average()` 计算流中 `double` 值的平均值。

文件名:AverageExample.java

输出

 
Average of odd numbers: 5.0 

示例 3:将字符串长度映射到 DoubleStream

在此示例中,我们将创建一个包含“apple”、“banana”、“cherry”、“date”、“elderberry”的字符串流。`filter(s -> s.length() > 5)` 过滤掉长度大于 5 个字符的字符串。`mapToDouble(s -> s.length())` 将每个剩余的字符串映射到其长度(作为 `double` 值)。

文件名:StringLengthMapToDoubleExample.java

输出

 
String: banana
String length as double: 6.0
String: cherry
String length as double: 6.0
String: elderberry
String length as double: 10.0  

示例 4:使用多个集合有条件地过滤数字

在此示例中,我们将创建两个名为 `list1` 和 `list2` 的列表。然后我们将列表转换为流,`mapToDouble(num -> Double.parseDouble(num))` 使用 `Double.parseDouble()` 将流中的每个字符串转换为 `double`。`filter(num -> (num * num) * 2 == 800)` 在示例 1 中,以及 `filter(num -> (num * num) * 2 == 242)` 在示例 2 中,根据平方乘以 2 等于 800 和 242 的条件过滤流。`forEach(System.out::println)` 打印每个过滤后的数字。

文件名:NumberFilterExample.java

输出

 
First set of numbers:
20.0
Second set of numbers:
11.0   

示例 5:计算字符串长度的平方

在此示例中,我们将创建两个名为 `list1` 和 `list2` 的列表。然后我们将列表转换为流,`mapToDouble(str -> str.length() * str.length())` 将每个字符串映射到其长度的平方(作为 `double`)。`forEach(System.out::println)` 打印每个计算出的平方值。

文件名:StringLengthSquareExample.java

输出

 
Example 1:
25.0
64.0
49.0
25.0
81.0   

示例 6:计算 BMI(身体质量指数)

在此示例中,我们将创建一个包含具有不同属性的 `Person` 对象的列表。流处理:`mapToDouble(person -> person.getWeight() / (person.getHeight() * person.getHeight()))` 使用每个人的体重除以其身高平方(BMI 公式)来计算 BMI。然后 `forEach(bmi -> System.out.println("BMI: " + bmi))` 打印每个人的 BMI。

文件名:BMICalculatorExample.java

输出

 
BMI Results:
BMI: 20.20
BMI: 22.09
BMI: 27.04
BMI: 17.58   

应用

1. 财务数据分析

在金融领域,分析交易数据或股票价格通常需要处理大量数据集以获得有意义的见解。例如,将交易金额映射到 `DoubleStream` 并计算平均值或总计等各种统计数据可以提供关键的财务见解。

2. 物联网设备中的数据处理

在物联网 (IoT) 应用中,设备通常会生成传感器数据流。Java 流可用于实时过滤、聚合或分析这些数据。例如,处理传感器读数以检测异常、计算平均值或基于历史数据预测趋势是在流处理中常见的任务。

3. 科学研究和数据分析

在科学研究中,分析实验数据或模拟通常需要高效地处理大量数据集。Java 流可以处理诸如将实验结果映射到数值、过滤异常值或计算多个实验的统计度量等任务。这种方法支持可重复的研究和数据驱动的决策。

4. 电子商务和客户分析

电子商务平台可以使用流来分析客户行为,例如购买模式、浏览历史或产品偏好。映射和聚合客户数据可以提供对客户细分、购买行为趋势或热门产品的见解。这些信息对于个性化营销策略和库存管理至关重要。