ZetCode

Java ToDoubleFunction 接口

最后修改时间:2025 年 4 月 16 日

java.util.function.ToDoubleFunction 接口表示一个接受一个参数并产生 double 类型结果的函数。它是一个函数式接口,具有单个抽象方法 applyAsDouble

ToDoubleFunction 是 Java 8 中添加的 Java 函数式编程实用程序的一部分。它经过专门设计,在处理基本 double 值时避免装箱。这提高了数值运算的性能。

ToDoubleFunction 接口概述

ToDoubleFunction 接口包含一个必须实现的抽象方法。该方法接受一个 T 类型的对象并返回一个基本 double 值。此接口中没有默认方法。

@FunctionalInterface
public interface ToDoubleFunction<T> {
    double applyAsDouble(T value);
}

上面的代码显示了 ToDoubleFunction 的简单结构。它使用泛型,其中 T 是输入类型。该接口使用 @FunctionalInterface 进行注解,以表明其单个抽象方法的性质。

ToDoubleFunction 的基本用法

使用 ToDoubleFunction 的最简单方法是使用 lambda 表达式。我们定义了如何将输入转换为 double 值。此示例计算字符串长度。

Main.java
package com.zetcode;

import java.util.function.ToDoubleFunction;

public class Main {

    public static void main(String[] args) {

        // Define function that returns string length as double
        ToDoubleFunction<String> lengthFunction = s -> (double) s.length();
        
        // Apply the function
        System.out.println("Length of 'hello': " + lengthFunction.applyAsDouble("hello"));
        System.out.println("Length of 'functional': " + lengthFunction.applyAsDouble("functional"));
        
        // Using method reference
        ToDoubleFunction<String> lengthMethodRef = String::length;
        System.out.println("Length via method ref: " + lengthMethodRef.applyAsDouble("method"));
    }
}

此示例演示了使用 lambda 和方法引用的基本 ToDoubleFunction 用法。该函数接受 String 并返回其长度作为 double。我们将其应用于不同的字符串。方法引用提供了简洁的语法。

带有自定义对象的 ToDoubleFunction

ToDoubleFunction 适用于自定义对象。我们可以从对象中提取数值属性。此示例计算产品税后价格。

Main.java
package com.zetcode;

import java.util.function.ToDoubleFunction;

class Product {
    String name;
    double price;
    
    Product(String name, double price) {
        this.name = name;
        this.price = price;
    }
}

public class Main {

    public static void main(String[] args) {

        // Function to calculate price with 20% tax
        ToDoubleFunction<Product> priceWithTax = p -> p.price * 1.20;
        
        Product laptop = new Product("Laptop", 999.99);
        Product phone = new Product("Phone", 599.99);
        
        System.out.println("Laptop with tax: " + priceWithTax.applyAsDouble(laptop));
        System.out.println("Phone with tax: " + priceWithTax.applyAsDouble(phone));
    }
}

此示例显示了带有自定义 Product 对象的 ToDoubleFunction。该函数计算包含税费的最终价格。我们将其应用于不同的产品实例。结果始终是基本 double 类型。

在 Stream 操作中使用 ToDoubleFunction

ToDoubleFunction 经常与 Java Stream 一起使用,用于数值转换。mapToDouble 操作接受一个 ToDoubleFunction。这使得能够进行有效的数值处理。

Main.java
package com.zetcode;

import java.util.Arrays;
import java.util.List;

public class Main {

    public static void main(String[] args) {

        List<String> words = Arrays.asList("apple", "banana", "cherry", "date");
        
        // Calculate average word length
        double avgLength = words.stream()
            .mapToDouble(String::length)  // ToDoubleFunction as method reference
            .average()
            .orElse(0);
            
        System.out.println("Average word length: " + avgLength);
        
        // Sum of squares of lengths
        double sumSquares = words.stream()
            .mapToDouble(s -> Math.pow(s.length(), 2))  // Lambda as ToDoubleFunction
            .sum();
            
        System.out.println("Sum of squares: " + sumSquares);
    }
}

此示例演示了在 Streams 中使用 ToDoubleFunction。我们使用方法引用和 lambda 将字符串转换为数值。流操作使用基本 double 类型以获得更好的性能。

带有集合的 ToDoubleFunction

ToDoubleFunction 可用于需要数值转换的集合操作。此示例显示了对集合的统计计算。

Main.java
package com.zetcode;

import java.util.Arrays;
import java.util.DoubleSummaryStatistics;
import java.util.List;
import java.util.function.ToDoubleFunction;

public class Main {

    public static void main(String[] args) {

        List<Integer> numbers = Arrays.asList(10, 20, 30, 40, 50);
        
        // Convert integers to their square roots
        ToDoubleFunction<Integer> sqrtFunction = n -> Math.sqrt(n);
        
        DoubleSummaryStatistics stats = numbers.stream()
            .mapToDouble(sqrtFunction)
            .summaryStatistics();
            
        System.out.println("Count: " + stats.getCount());
        System.out.println("Average: " + stats.getAverage());
        System.out.println("Max: " + stats.getMax());
        System.out.println("Min: " + stats.getMin());
        System.out.println("Sum: " + stats.getSum());
    }
}

此示例使用 ToDoubleFunction 计算整数的平方根。然后,我们从结果中生成统计数据。该函数能够在统计操作之前进行干净的数值转换。

带有数组的 ToDoubleFunction

使用 ToDoubleFunction 可以有效地处理数组。此示例显示了数组转换和归约操作。

Main.java
package com.zetcode;

import java.util.Arrays;
import java.util.function.ToDoubleFunction;

public class Main {

    public static void main(String[] args) {

        String[] temperatures = {"23.5", "18.2", "31.7", "25.0", "19.8"};
        
        // Parse strings to doubles
        ToDoubleFunction<String> parseDouble = s -> Double.parseDouble(s);
        
        double[] values = Arrays.stream(temperatures)
            .mapToDouble(parseDouble)
            .toArray();
            
        System.out.println("Parsed values: " + Arrays.toString(values));
        
        // Find maximum temperature
        double max = Arrays.stream(temperatures)
            .mapToDouble(Double::parseDouble)  // Method reference alternative
            .max()
            .orElse(Double.NaN);
            
        System.out.println("Maximum temperature: " + max);
    }
}

此示例处理一个温度字符串数组。我们使用 ToDoubleFunction 将字符串解析为 double 类型。结果收集在一个数组中,用于查找最大值。同时显示了 lambda 和方法引用的形式。

将 ToDoubleFunction 与其他函数式接口结合使用

ToDoubleFunction 可以与其他函数式接口结合使用,以进行更复杂的操作。此示例显示了在转换之前的过滤。

Main.java
package com.zetcode;

import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
import java.util.function.ToDoubleFunction;

public class Main {

    public static void main(String[] args) {

        List<String> mixedValues = Arrays.asList("12.5", "invalid", "45.2", "0", "3.14");
        
        Predicate<String> isNumeric = s -> {
            try {
                Double.parseDouble(s);
                return true;
            } catch (NumberFormatException e) {
                return false;
            }
        };
        
        ToDoubleFunction<String> parseSafe = s -> {
            try {
                return Double.parseDouble(s);
            } catch (NumberFormatException e) {
                return 0.0;
            }
        };
        
        // Filter valid numbers and parse them
        double sum = mixedValues.stream()
            .filter(isNumeric)
            .mapToDouble(parseSafe)
            .sum();
            
        System.out.println("Sum of valid numbers: " + sum);
        
        // Alternative with handling in ToDoubleFunction
        double sumAlt = mixedValues.stream()
            .mapToDouble(parseSafe)
            .sum();
            
        System.out.println("Sum with default handling: " + sumAlt);
    }
}

此示例结合了 Predicate 和 ToDoubleFunction,以安全地处理混合输入。我们首先过滤有效数字,然后解析它们。另一种方法是在 ToDoubleFunction 本身中处理无效值。

基本类型特化比较

Java 提供了几个针对基本类型的函数式接口。此示例将 ToDoubleFunction 与针对不同基本类型的类似接口进行比较。

Main.java
package com.zetcode;

import java.util.function.ToIntFunction;
import java.util.function.ToLongFunction;
import java.util.function.ToDoubleFunction;

public class Main {

    public static void main(String[] args) {

        // Different primitive specialized functions
        ToIntFunction<String> toLengthInt = String::length;
        ToLongFunction<String> toLengthLong = s -> (long) s.length();
        ToDoubleFunction<String> toLengthDouble = s -> (double) s.length();
        
        System.out.println("As int: " + toLengthInt.applyAsInt("hello"));
        System.out.println("As long: " + toLengthLong.applyAsLong("world"));
        System.out.println("As double: " + toLengthDouble.applyAsDouble("java"));
        
        // When precision matters
        ToDoubleFunction<Double> circleArea = r -> Math.PI * r * r;
        System.out.println("Area of circle with r=2.5: " + circleArea.applyAsDouble(2.5));
    }
}

此示例将 ToDoubleFunction 与 ToIntFunction 和 ToLongFunction 进行比较。每个接口都专门用于不同的基本返回类型。当需要小数精度时,ToDoubleFunction 是理想的选择,例如在几何计算中。

来源

Java ToDoubleFunction 接口文档

在本文中,我们介绍了 Java ToDoubleFunction 接口的基本使用模式。这个专门的函数式接口对于在 Java 应用程序中进行有效的数值处理非常有用。

作者

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

列出所有Java教程