Java DoubleSupplier Interface
Last modified: April 16, 2025
The java.util.function.DoubleSupplier
interface represents a supplier
of double-valued results. It is a functional interface with a single abstract
method getAsDouble
. This interface requires no input arguments.
DoubleSupplier
is part of Java's functional programming utilities
added in Java 8. It is useful when you need to generate or supply double values
without any input. The interface is often used in lazy evaluation scenarios.
DoubleSupplier Interface Overview
DoubleSupplier
interface contains one abstract method. The key
method getAsDouble
returns a double value. There are no default
or static methods in this interface.
@FunctionalInterface public interface DoubleSupplier { double getAsDouble(); }
The code above shows the simple structure of DoubleSupplier
. It is
annotated with @FunctionalInterface to indicate its single abstract method
nature. The interface is specialized for primitive double values.
Basic DoubleSupplier Usage
The simplest way to use DoubleSupplier is with lambda expressions. We define how to generate the double value in the getAsDouble method. The example supplies random numbers.
package com.zetcode; import java.util.function.DoubleSupplier; public class Main { public static void main(String[] args) { // Define a supplier that generates random numbers DoubleSupplier randomSupplier = () -> Math.random(); // Get values from the supplier System.out.println("Random 1: " + randomSupplier.getAsDouble()); System.out.println("Random 2: " + randomSupplier.getAsDouble()); // Supplier with fixed value DoubleSupplier fixedSupplier = () -> 3.1415; System.out.println("Fixed value: " + fixedSupplier.getAsDouble()); } }
This example demonstrates basic DoubleSupplier usage with lambda expressions. The randomSupplier generates new random numbers each time it's called. The fixedSupplier always returns the same value. Suppliers are lazy evaluated.
DoubleSupplier with Method Reference
Method references provide a concise way to create DoubleSupplier instances when existing methods match the interface. This works for methods that take no parameters and return double.
package com.zetcode; import java.util.function.DoubleSupplier; public class Main { public static void main(String[] args) { // Create a supplier using method reference DoubleSupplier piSupplier = Math::PI; DoubleSupplier nanSupplier = Double::NaN; System.out.println("PI value: " + piSupplier.getAsDouble()); System.out.println("NaN value: " + nanSupplier.getAsDouble()); // Instance method reference Random random = new Random(); DoubleSupplier randomSupplier = random::nextDouble; System.out.println("Random from instance: " + randomSupplier.getAsDouble()); } }
This example shows DoubleSupplier creation via method references. We use static methods from Math and Double classes, and an instance method from Random. Method references make the code more concise and readable.
DoubleSupplier in Stream Generation
DoubleSupplier is useful for generating infinite streams of double values. The
DoubleStream.generate
method accepts a DoubleSupplier to produce
stream elements. This enables lazy generation of values.
package com.zetcode; import java.util.function.DoubleSupplier; import java.util.stream.DoubleStream; public class Main { public static void main(String[] args) { // Create a supplier for sequence numbers double[] counter = {0.0}; DoubleSupplier sequenceSupplier = () -> counter[0] += 1.0; // Generate stream of 5 sequence numbers DoubleStream.generate(sequenceSupplier) .limit(5) .forEach(System.out::println); // Random numbers stream DoubleStream.generate(Math::random) .limit(3) .forEach(d -> System.out.printf("Random: %.4f%n", d)); } }
This example demonstrates DoubleSupplier in stream generation. We create a sequence supplier that increments a counter and a random number supplier. The stream is limited to avoid infinite processing. Each element is generated on demand.
Lazy Evaluation with DoubleSupplier
DoubleSupplier enables lazy evaluation by deferring value generation until needed. This is useful for expensive computations or when values might not be used. The supplier acts as a value factory.
package com.zetcode; import java.util.function.DoubleSupplier; public class Main { public static void main(String[] args) { // Expensive computation wrapped in supplier DoubleSupplier expensiveCalc = () -> { System.out.println("Performing expensive calculation..."); try { Thread.sleep(1000); // Simulate long computation } catch (InterruptedException e) { e.printStackTrace(); } return Math.PI * Math.E; }; System.out.println("Supplier created, but no calculation yet"); // Only calculate when actually needed if (args.length > 0) { System.out.println("Result: " + expensiveCalc.getAsDouble()); } } }
This example shows lazy evaluation with DoubleSupplier. The expensive calculation is only performed when getAsDouble() is called. Without the supplier, the computation would happen immediately during initialization. Lazy evaluation improves performance.
DoubleSupplier for Configuration Values
DoubleSupplier can provide flexible configuration values. The actual value can change between calls or be determined at runtime. This is useful for dynamic configuration systems.
package com.zetcode; import java.util.function.DoubleSupplier; import java.time.LocalTime; public class Main { public static void main(String[] args) { // Time-based discount factor DoubleSupplier discountSupplier = () -> { int hour = LocalTime.now().getHour(); return hour >= 20 || hour < 6 ? 0.9 : 1.0; // 10% discount at night }; System.out.println("Current discount factor: " + discountSupplier.getAsDouble()); // Environment-based configuration DoubleSupplier configSupplier = () -> "prod".equals(System.getenv("APP_ENV")) ? 1.0 : 0.5; System.out.println("Config value: " + configSupplier.getAsDouble()); } }
This example demonstrates DoubleSupplier for dynamic configuration. The discount supplier changes value based on current time. The config supplier reads from environment variables. Suppliers enable runtime value determination.
Combining DoubleSuppliers
While DoubleSupplier has no built-in composition methods, we can combine suppliers manually to create more complex value generators. This allows building sophisticated suppliers from simple ones.
package com.zetcode; import java.util.function.DoubleSupplier; public class Main { public static void main(String[] args) { // Base suppliers DoubleSupplier randomSupplier = Math::random; DoubleSupplier fixedSupplier = () -> 10.0; // Combined supplier - average of random and fixed DoubleSupplier averageSupplier = () -> (randomSupplier.getAsDouble() + fixedSupplier.getAsDouble()) / 2; System.out.println("Average value: " + averageSupplier.getAsDouble()); // Conditional supplier boolean useHighPrecision = true; DoubleSupplier precisionSupplier = useHighPrecision ? () -> Math.PI : () -> 3.14; System.out.println("PI value: " + precisionSupplier.getAsDouble()); } }
This example shows how to combine DoubleSuppliers. We create an average supplier that combines two other suppliers. We also demonstrate a conditional supplier that changes behavior based on a flag. Composition enables flexible value generation.
DoubleSupplier vs Other Suppliers
Java provides several supplier interfaces for different types. DoubleSupplier is specialized for primitive doubles, avoiding boxing overhead. Other suppliers like Supplier<Double> work with wrapper objects.
package com.zetcode; import java.util.function.DoubleSupplier; import java.util.function.Supplier; public class Main { public static void main(String[] args) { // Primitive double supplier DoubleSupplier primitiveSupplier = () -> Math.random(); // Wrapper Double supplier Supplier<Double> wrapperSupplier = () -> Math.random(); System.out.println("Primitive: " + primitiveSupplier.getAsDouble()); System.out.println("Wrapper: " + wrapperSupplier.get()); // Performance consideration long start = System.nanoTime(); for (int i = 0; i < 1_000_000; i++) { primitiveSupplier.getAsDouble(); } System.out.println("Primitive time: " + (System.nanoTime() - start)/1_000_000 + " ms"); start = System.nanoTime(); for (int i = 0; i < 1_000_000; i++) { wrapperSupplier.get(); } System.out.println("Wrapper time: " + (System.nanoTime() - start)/1_000_000 + " ms"); } }
This example compares DoubleSupplier with Supplier<Double>. The primitive version avoids boxing overhead and is more efficient for intensive numeric operations. The wrapper version is needed when working with generic APIs.
Source
Java DoubleSupplier Interface Documentation
In this article, we've covered the essential methods and features of the Java DoubleSupplier interface. Understanding these concepts is crucial for functional programming and efficient numeric operations in Java applications.
Author
List all Java tutorials.