ZetCode

Java DoubleConsumer 接口

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

java.util.function.DoubleConsumer 接口表示接受一个双精度浮点值参数并且不返回结果的操作。它是一个函数式接口,只有一个抽象方法 accept。DoubleConsumer 常用在消耗原始双精度浮点值而不返回任何内容的操作中。

DoubleConsumer 是 Java 8 中添加的函数式编程实用程序的一部分。它支持对双精度浮点值进行行为参数化,并有助于编写更简洁的代码。该接口提供了一个用于消费者链的默认方法。

DoubleConsumer 接口概述

DoubleConsumer 接口包含一个抽象方法和一个默认方法。关键方法 accept 对输入执行操作。默认方法支持消费者链。

@FunctionalInterface
public interface DoubleConsumer {
    void accept(double value);
    
    default DoubleConsumer andThen(DoubleConsumer after);
}

上述代码显示了 DoubleConsumer 接口的结构。它对原始双精度浮点值进行操作。该接口使用 @FunctionalInterface 注解来指示其单一抽象方法的性质。

DoubleConsumer 的基本用法

使用 DoubleConsumer 的最简单方法是使用 lambda 表达式。我们在 accept 方法中定义如何处理双精度浮点值。该示例使用格式化打印双精度浮点值。

Main.java
package com.zetcode;

import java.util.function.DoubleConsumer;

public class Main {

    public static void main(String[] args) {

        // Define a consumer that prints formatted double values
        DoubleConsumer printFormatted = d -> 
            System.out.printf("Value: %.2f%n", d);
        
        // Use the consumer
        printFormatted.accept(3.14159);
        printFormatted.accept(2.71828);
        
        // Consumer using method reference
        DoubleConsumer printer = System.out::println;
        printer.accept(1.41421);
    }
}

此示例演示了使用 lambda 和方法引用的 DoubleConsumer 的基本用法。printFormatted 消费者格式化并打印双精度浮点数。printer 消费者使用方法引用到 System.out.println 进行直接输出。

带 andThen 的 DoubleConsumer

andThen 方法允许链接消费者,其中每个消费者按顺序处理相同的值。这使得可以从简单的消费者创建复杂的处理管道。

Main.java
package com.zetcode;

import java.util.function.DoubleConsumer;

public class Main {

    public static void main(String[] args) {

        // First consumer logs the value
        DoubleConsumer logger = d -> 
            System.out.println("Logging: " + d);
        
        // Second consumer calculates square
        DoubleConsumer squarer = d -> 
            System.out.println("Square: " + (d * d));
        
        // Chain the consumers
        DoubleConsumer logThenSquare = logger.andThen(squarer);
        
        System.out.println("Processing 3.0:");
        logThenSquare.accept(3.0);
        
        System.out.println("\nProcessing 1.5:");
        logThenSquare.accept(1.5);
    }
}

此示例展示了使用 andThen 的消费者链。输入值首先被记录,然后被平方。这两个操作将按顺序对传递给组合消费者的每个值执行。

DoubleConsumer 在流处理中

DoubleConsumer 常用在 DoubleStream 中用于处理原始双精度浮点值。forEach 终端操作接受一个 DoubleConsumer 来处理每个流元素。

Main.java
package com.zetcode;

import java.util.stream.DoubleStream;

public class Main {

    public static void main(String[] args) {

        // Create a stream of double values
        DoubleStream values = DoubleStream.of(1.1, 2.2, 3.3, 4.4, 5.5);
        
        // Define a consumer that processes each value
        values.forEach(d -> {
            double rounded = Math.round(d * 10) / 10.0;
            System.out.println("Original: " + d + ", Rounded: " + rounded);
        });
        
        // Another example with method reference
        DoubleStream.of(0.5, 1.5, 2.5).forEach(System.out::println);
    }
}

此示例演示了 DoubleConsumer 在 DoubleStream 处理中的用法。我们定义了一个消费者,该消费者对每个值进行四舍五入并打印。方法引用为简单的输出操作提供了一种简洁的替代方案。

在 DoubleConsumer 中存储状态

虽然通常不鼓励用于纯函数,但消费者可以在需要时维护状态。此示例展示了一个消费者,该消费者跟踪其处理的值的统计信息。

Main.java
package com.zetcode;

import java.util.function.DoubleConsumer;

public class Main {

    public static void main(String[] args) {

        // Consumer that tracks statistics
        class StatsConsumer implements DoubleConsumer {
            private double sum = 0;
            private int count = 0;
            private double min = Double.MAX_VALUE;
            private double max = Double.MIN_VALUE;
            
            @Override
            public void accept(double value) {
                sum += value;
                count++;
                min = Math.min(min, value);
                max = Math.max(max, value);
            }
            
            public void printStats() {
                System.out.printf("Count: %d, Sum: %.2f, Avg: %.2f%n", 
                    count, sum, sum/count);
                System.out.printf("Min: %.2f, Max: %.2f%n", min, max);
            }
        }
        
        StatsConsumer stats = new StatsConsumer();
        
        // Process some values
        stats.accept(5.5);
        stats.accept(3.2);
        stats.accept(7.8);
        stats.accept(1.1);
        
        // Print collected statistics
        stats.printStats();
    }
}

此示例显示了一个有状态的 DoubleConsumer 实现。StatsConsumer 跟踪处理值的总和、计数、最小值和最大值。虽然函数式接口通常是无状态的,但此示例演示了它们在需要时的灵活性。

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

DoubleConsumer 可以与其他函数式接口有效地结合使用,以创建更复杂的操作。此示例展示了它与 DoublePredicate 的配对。

Main.java
package com.zetcode;

import java.util.function.DoubleConsumer;
import java.util.function.DoublePredicate;

public class Main {

    public static void main(String[] args) {

        // Predicate to check if value is positive
        DoublePredicate isPositive = d -> d > 0;
        
        // Consumer for positive values
        DoubleConsumer positiveConsumer = d -> 
            System.out.println("Processing positive: " + d);
        
        // Consumer for negative values
        DoubleConsumer negativeConsumer = d -> 
            System.out.println("Processing negative: " + d);
        
        // Combined processor
        DoubleConsumer processor = d -> {
            if (isPositive.test(d)) {
                positiveConsumer.accept(d);
            } else {
                negativeConsumer.accept(d);
            }
        };
        
        // Test the processor
        processor.accept(3.14);
        processor.accept(-2.71);
        processor.accept(0.0);
    }
}

此示例演示了将 DoubleConsumer 与 DoublePredicate 结合使用。我们为正值和负值创建不同的消费者,然后将它们与谓词检查相结合。这种模式支持条件处理管道。

DoubleConsumer 在现实世界中的应用场景

此示例显示了一个更实际的用例,其中 DoubleConsumer 处理来自传感器的温度读数,包括验证和多个处理步骤。

Main.java
package com.zetcode;

import java.util.function.DoubleConsumer;

public class Main {

    public static void main(String[] args) {

        // Valid temperature range
        final double MIN_TEMP = -50.0;
        final double MAX_TEMP = 100.0;
        
        // Consumer to validate temperature
        DoubleConsumer validator = temp -> {
            if (temp < MIN_TEMP || temp > MAX_TEMP) {
                throw new IllegalArgumentException(
                    String.format("Invalid temperature: %.1f", temp));
            }
        };
        
        // Consumer to convert to Fahrenheit
        DoubleConsumer fahrenheitConverter = temp -> {
            double fahr = temp * 9/5 + 32;
            System.out.printf("%.1f°C = %.1f°F%n", temp, fahr);
        };
        
        // Consumer to check for extreme temperatures
        DoubleConsumer extremeChecker = temp -> {
            if (temp > 35.0) {
                System.out.println("WARNING: High temperature alert!");
            } else if (temp < 0.0) {
                System.out.println("WARNING: Freezing temperature!");
            }
        };
        
        // Combined processing pipeline
        DoubleConsumer tempProcessor = validator
            .andThen(extremeChecker)
            .andThen(fahrenheitConverter);
        
        // Process some temperature readings
        double[] readings = {25.5, -1.2, 36.7, 150.0, -60.0};
        
        for (double temp : readings) {
            try {
                System.out.println("\nProcessing: " + temp);
                tempProcessor.accept(temp);
            } catch (IllegalArgumentException e) {
                System.out.println("Error: " + e.getMessage());
            }
        }
    }
}

此示例演示了 DoubleConsumer 在温度处理中的实际应用。我们链接验证、检查和转换操作。管道通过异常处理优雅地处理无效值。

来源

Java DoubleConsumer 接口文档

在本文中,我们涵盖了 Java DoubleConsumer 接口的基本方法和特性。理解这些概念对于在函数式编程和流操作中处理原始双精度浮点值至关重要。

作者

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

列出所有Java教程