Java DoubleConsumer Interface
Last modified: April 16, 2025
The java.util.function.DoubleConsumer interface represents an
operation that accepts a single double-valued argument and returns no result.
It is a functional interface with a single abstract method accept.
DoubleConsumer is commonly used for operations that consume primitive double
values without returning anything.
DoubleConsumer is part of Java's functional programming utilities
added in Java 8. It enables behavior parameterization for double values and
helps write more concise code. The interface provides a default method for
consumer chaining.
DoubleConsumer Interface Overview
DoubleConsumer interface contains one abstract method and one
default method. The key method accept performs the operation on
the input. The default method enables consumer chaining.
@FunctionalInterface
public interface DoubleConsumer {
void accept(double value);
default DoubleConsumer andThen(DoubleConsumer after);
}
The code above shows the structure of DoubleConsumer interface.
It operates on primitive double values. The interface is annotated with
@FunctionalInterface to indicate its single abstract method nature.
Basic DoubleConsumer Usage
The simplest way to use DoubleConsumer is with lambda expressions. We define what to do with the double value in the accept method. The example prints double values with formatting.
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);
}
}
This example demonstrates basic DoubleConsumer usage with lambda and method reference. The printFormatted consumer formats and prints doubles. The printer consumer uses method reference to System.out.println for direct output.
DoubleConsumer with andThen
The andThen method allows chaining consumers where each consumer
processes the same value in sequence. This enables creating complex processing
pipelines from simple consumers.
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);
}
}
This example shows consumer chaining with andThen. The input value
first gets logged, then squared. Both operations happen in sequence for each
value passed to the combined consumer.
DoubleConsumer in Stream Processing
DoubleConsumer is commonly used with DoubleStream for processing primitive double values. The forEach terminal operation accepts a DoubleConsumer to process each stream element.
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);
}
}
This example demonstrates DoubleConsumer usage in DoubleStream processing. We define a consumer that rounds and prints each value. Method reference provides a concise alternative for simple output operations.
Storing State in DoubleConsumer
While generally discouraged for pure functions, consumers can maintain state when needed. This example shows a consumer that tracks statistics about the values it processes.
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();
}
}
This example shows a stateful DoubleConsumer implementation. The StatsConsumer tracks sum, count, min and max of processed values. While functional interfaces are often stateless, this demonstrates their flexibility when needed.
Combining DoubleConsumer with Other Functional Interfaces
DoubleConsumer can be effectively combined with other functional interfaces to create more complex operations. This example shows pairing it with DoublePredicate.
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);
}
}
This example demonstrates combining DoubleConsumer with DoublePredicate. We create different consumers for positive and negative values, then combine them with a predicate check. This pattern enables conditional processing pipelines.
DoubleConsumer in Real-World Scenario
This example shows a more practical use case where DoubleConsumer processes temperature readings from a sensor, with validation and multiple processing steps.
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());
}
}
}
}
This example demonstrates a realistic use of DoubleConsumer for temperature processing. We chain validation, checking, and conversion operations. The pipeline handles invalid values gracefully with exception handling.
Source
Java DoubleConsumer Interface Documentation
In this article, we've covered the essential methods and features of the Java DoubleConsumer interface. Understanding these concepts is crucial for processing primitive double values in functional programming and stream operations.
Author
List all Java tutorials.