Java ToDoubleBiFunction 接口
最后修改时间:2025 年 4 月 16 日
java.util.function.ToDoubleBiFunction 接口表示一个接受两个参数并产生 double 类型结果的函数。它是一个函数式接口,只有一个抽象方法 applyAsDouble。
ToDoubleBiFunction 是 Java 8 中添加的 Java 函数式编程工具的一部分。它专门用于原始 double 类型的输出,以避免装箱开销。此接口对数值计算非常有用。
ToDoubleBiFunction 接口概述
ToDoubleBiFunction 接口包含一个抽象方法,该方法接受两个参数并返回一个 double 值。它使用两个泛型类型参数化,用于输入参数。
@FunctionalInterface
public interface ToDoubleBiFunction<T, U> {
double applyAsDouble(T t, U u);
}
上面的代码展示了 ToDoubleBiFunction 的结构。它使用泛型,其中 T 和 U 是输入类型。该接口使用 @FunctionalInterface 注解,以表明其单抽象方法性质。
ToDoubleBiFunction 的基本用法
使用 ToDoubleBiFunction 的最简单方法是使用 lambda 表达式。我们定义如何处理两个输入以产生一个 double 结果。该示例计算产品价格。
package com.zetcode;
import java.util.function.ToDoubleBiFunction;
public class Main {
public static void main(String[] args) {
// Calculate total price (quantity * unitPrice)
ToDoubleBiFunction<Integer, Double> calculateTotal =
(quantity, unitPrice) -> quantity * unitPrice;
double total1 = calculateTotal.applyAsDouble(5, 12.99);
double total2 = calculateTotal.applyAsDouble(3, 8.50);
System.out.println("Total 1: " + total1);
System.out.println("Total 2: " + total2);
}
}
此示例演示了 ToDoubleBiFunction 的基本用法。lambda 表达式接受 Integer 数量和 Double 单价,并返回它们的乘积。通过直接使用原始 double,我们避免了装箱/拆箱开销。
计算欧几里得距离
ToDoubleBiFunction 非常适合需要两个输入的数学运算。此示例计算两个 2D 点之间的欧几里得距离。
package com.zetcode;
import java.util.function.ToDoubleBiFunction;
public class Main {
public static void main(String[] args) {
// Calculate distance between two points (x1,y1) and (x2,y2)
ToDoubleBiFunction<Point, Point> distanceCalculator =
(p1, p2) -> Math.sqrt(Math.pow(p2.x - p1.x, 2) +
Math.pow(p2.y - p1.y, 2));
Point pointA = new Point(1, 2);
Point pointB = new Point(4, 6);
double distance = distanceCalculator.applyAsDouble(pointA, pointB);
System.out.printf("Distance between points: %.2f%n", distance);
}
}
class Point {
double x, y;
Point(double x, double y) {
this.x = x;
this.y = y;
}
}
此示例展示了 ToDoubleBiFunction 与自定义对象的使用。lambda 表达式使用标准公式计算距离。结果作为原始 double 返回,以便在数值运算中获得更好的性能。
加权平均计算
ToDoubleBiFunction 可以处理值的集合。此示例计算来自两个值和权重数组的加权平均值。
package com.zetcode;
import java.util.function.ToDoubleBiFunction;
public class Main {
public static void main(String[] args) {
// Calculate weighted average
ToDoubleBiFunction<double[], double[]> weightedAverage =
(values, weights) -> {
if (values.length != weights.length) {
throw new IllegalArgumentException("Arrays must be same length");
}
double sum = 0;
double weightSum = 0;
for (int i = 0; i < values.length; i++) {
sum += values[i] * weights[i];
weightSum += weights[i];
}
return sum / weightSum;
};
double[] scores = {90, 85, 78};
double[] weights = {0.3, 0.4, 0.3};
double average = weightedAverage.applyAsDouble(scores, weights);
System.out.printf("Weighted average: %.2f%n", average);
}
}
此示例演示了 ToDoubleBiFunction 的复杂计算。lambda 表达式接受两个 double 数组并计算它们的加权平均值。输入验证确保在处理之前数组具有匹配的长度。
与集合一起使用
ToDoubleBiFunction 可以与 Java 集合很好地配合使用。此示例处理两个映射,以查找它们的值之间的相关性。
package com.zetcode;
import java.util.Map;
import java.util.function.ToDoubleBiFunction;
public class Main {
public static void main(String[] args) {
// Calculate correlation between two maps' values
ToDoubleBiFunction<Map<String, Double>, Map<String, Double>> correlation =
(map1, map2) -> {
double sumX = 0, sumY = 0, sumXY = 0;
double sumX2 = 0, sumY2 = 0;
int n = 0;
for (String key : map1.keySet()) {
if (map2.containsKey(key)) {
double x = map1.get(key);
double y = map2.get(key);
sumX += x;
sumY += y;
sumXY += x * y;
sumX2 += x * x;
sumY2 += y * y;
n++;
}
}
if (n == 0) return 0;
double numerator = sumXY - (sumX * sumY) / n;
double denominator = Math.sqrt(
(sumX2 - (sumX * sumX) / n) *
(sumY2 - (sumY * sumY) / n);
return numerator / denominator;
};
Map<String, Double> testScores = Map.of(
"Alice", 85.0, "Bob", 72.0, "Charlie", 90.0);
Map<String, Double> studyHours = Map.of(
"Alice", 12.5, "Bob", 8.0, "Charlie", 15.0);
double corr = correlation.applyAsDouble(testScores, studyHours);
System.out.printf("Correlation coefficient: %.2f%n", corr);
}
}
这个高级示例展示了 ToDoubleBiFunction 处理两个映射。它计算匹配值之间的皮尔逊相关系数。该实现使用原始 double 进行所有数学运算,以提高效率。
与其他函数式接口组合
ToDoubleBiFunction 可以与其他函数式接口组合使用。此示例展示了与 Function 组合以进行更复杂的转换。
package com.zetcode;
import java.util.function.Function;
import java.util.function.ToDoubleBiFunction;
public class Main {
public static void main(String[] args) {
// Convert string pairs to similarity score (0-1)
ToDoubleBiFunction<String, String> stringSimilarity =
(s1, s2) -> {
int matches = 0;
int length = Math.min(s1.length(), s2.length());
for (int i = 0; i < length; i++) {
if (s1.charAt(i) == s2.charAt(i)) {
matches++;
}
}
return (double) matches / Math.max(s1.length(), s2.length());
};
// Format similarity score as percentage
Function<Double, String> toPercent =
score -> String.format("%.0f%%", score * 100);
double similarity = stringSimilarity.applyAsDouble("hello", "hallo");
String percentage = toPercent.apply(similarity);
System.out.println("String similarity: " + percentage);
}
}
此示例将 ToDoubleBiFunction 与 Function 结合使用。第一个计算字符串相似度(double),第二个将其格式化为百分比。这展示了函数式接口如何在处理管道中协同工作。
在流操作中使用
ToDoubleBiFunction 可以在流处理中使用。此示例计算产品对的平均单价。
package com.zetcode;
import java.util.List;
import java.util.function.ToDoubleBiFunction;
public class Main {
public static void main(String[] args) {
// Calculate average price per unit for two products
ToDoubleBiFunction<Product, Product> avgPricePerUnit =
(p1, p2) -> (p1.price / p1.quantity + p2.price / p2.quantity) / 2;
List<Product> products = List.of(
new Product(5, 25.0), // 5 units for $25
new Product(3, 21.0), // 3 units for $21
new Product(10, 45.0) // 10 units for $45
);
// Compare each pair of products
for (int i = 0; i < products.size(); i++) {
for (int j = i + 1; j < products.size(); j++) {
double avg = avgPricePerUnit.applyAsDouble(
products.get(i), products.get(j));
System.out.printf("Avg price for pair %d-%d: $%.2f%n",
i+1, j+1, avg);
}
}
}
}
class Product {
int quantity;
double price;
Product(int quantity, double price) {
this.quantity = quantity;
this.price = price;
}
}
此示例演示了 ToDoubleBiFunction 在嵌套循环中处理产品对。该函数使用原始 double 算术有效地计算平均单价。结果格式化以便显示。
专门的原始类型变体
Java 提供了 ToDoubleBiFunction 的专门版本,用于原始输入。这些避免了在使用原始数据类型时装箱开销。
package com.zetcode;
import java.util.function.IntToDoubleFunction;
import java.util.function.ToDoubleBiFunction;
import java.util.function.ToIntBiFunction;
public class Main {
public static void main(String[] args) {
// Standard ToDoubleBiFunction with Integer objects
ToDoubleBiFunction<Integer, Integer> objCalc =
(a, b) -> Math.sqrt(a * a + b * b);
// Primitive specialized version (hypot is more accurate)
ToDoubleBiFunction<Integer, Integer> primCalc =
(a, b) -> Math.hypot(a, b);
System.out.println("Object version result: " + objCalc.applyAsDouble(3, 4));
System.out.println("Primitive version result: " + primCalc.applyAsDouble(3, 4));
// Note: Java doesn't have IntIntToDoubleFunction, but hypot is optimized
}
}
此示例比较了标准方法和原始类型优化的方法。虽然 Java 没有 IntIntToDoubleFunction,但 Math.hypot 等方法已针对原始类型进行了优化。该示例展示了如何通过数值运算来最大化性能。
来源
在本文中,我们介绍了 Java ToDoubleBiFunction 接口的基本方法和功能。理解这些概念对于在现代 Java 应用程序中进行高效的数值处理至关重要。
作者
列出所有Java教程。