ZetCode

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 结果。该示例计算产品价格。

Main.java
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 点之间的欧几里得距离。

Main.java
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 可以处理值的集合。此示例计算来自两个值和权重数组的加权平均值。

Main.java
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 集合很好地配合使用。此示例处理两个映射,以查找它们的值之间的相关性。

Main.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 组合以进行更复杂的转换。

Main.java
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 可以在流处理中使用。此示例计算产品对的平均单价。

Main.java
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 的专门版本,用于原始输入。这些避免了在使用原始数据类型时装箱开销。

Main.java
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 ToDoubleBiFunction 接口的基本方法和功能。理解这些概念对于在现代 Java 应用程序中进行高效的数值处理至关重要。

作者

我叫 Jan Bodnar,是一位经验丰富的程序员,在该领域拥有多年经验。我于 2007 年开始撰写编程文章,此后撰写了 1,400 多篇文章和八本电子书。凭借超过八年的教学经验,我致力于分享我的知识并帮助其他人掌握编程概念。

列出所有Java教程