Java Supplier 接口
最后修改时间:2025 年 4 月 16 日
java.util.function.Supplier
接口表示结果的提供者。它是一个函数式接口,只有一个抽象方法 get
。Supplier 不接受任何参数,但会生成一个值。
Supplier
是 Java 8 中添加的 Java 函数式编程实用程序的一部分。它对于延迟求值、对象创建和值生成场景非常有用。该接口经常与 Optional 和 Streams 一起使用。
Supplier 接口概述
Supplier
接口包含一个抽象方法,没有默认方法。关键方法 get
返回结果,不接受任何输入参数。它是一个纯粹的值生成器。
@FunctionalInterface public interface Supplier<T> { T get(); }
以上代码展示了 Supplier
接口的简单结构。它使用泛型,其中 T 是提供结果的类型。该接口使用 @FunctionalInterface 进行注解,以指示其单一抽象方法。
Supplier 的基本用法
使用 Supplier 的最简单方法是使用 lambda 表达式。我们在 get 方法中定义如何生成值。此示例提供随机数。
package com.zetcode; import java.util.function.Supplier; import java.util.Random; public class Main { public static void main(String[] args) { // Define a supplier for random numbers Supplier<Integer> randomSupplier = () -> new Random().nextInt(100); // Get values from supplier System.out.println("Random 1: " + randomSupplier.get()); System.out.println("Random 2: " + randomSupplier.get()); // Supplier for current timestamp Supplier<Long> timeSupplier = System::currentTimeMillis; System.out.println("Current time: " + timeSupplier.get()); } }
此示例演示了 Supplier 与 lambda 和方法引用的基本用法。randomSupplier 在调用 get() 时生成随机整数。timeSupplier 使用方法引用来提供当前时间戳。
用于对象创建的 Supplier
Supplier 经常用于对象创建,尤其是在您需要延迟实例化或按需创建对象时。这使得延迟求值成为可能。
package com.zetcode; import java.util.function.Supplier; class Product { private String name; private double price; public Product(String name, double price) { this.name = name; this.price = price; System.out.println("Creating product: " + name); } @Override public String toString() { return name + " ($" + price + ")"; } } public class Main { public static void main(String[] args) { // Supplier for product creation Supplier<Product> productSupplier = () -> new Product("Laptop", 999.99); System.out.println("Supplier defined, but product not created yet"); // Only creates product when get() is called Product p1 = productSupplier.get(); Product p2 = productSupplier.get(); System.out.println("Products created: " + p1 + ", " + p2); } }
此示例显示了用于延迟对象创建的 Supplier。Product 对象仅在调用 get() 时才被实例化。这演示了使用 Supplier 的延迟初始化模式。
带有 Optional 的 Supplier
Supplier 经常与 Optional 的 orElseGet 方法一起使用,仅在需要时提供回退值。当回退创建成本较高时,这比 orElse 更有效。
package com.zetcode; import java.util.Optional; import java.util.function.Supplier; public class Main { public static void main(String[] args) { Optional<String> emptyOptional = Optional.empty(); Optional<String> presentOptional = Optional.of("Hello"); // Expensive fallback operation Supplier<String> fallbackSupplier = () -> { System.out.println("Creating fallback value"); return "Default Value"; }; // orElseGet uses Supplier (lazy) String value1 = emptyOptional.orElseGet(fallbackSupplier); String value2 = presentOptional.orElseGet(fallbackSupplier); System.out.println("Value 1: " + value1); System.out.println("Value 2: " + value2); // Compare with orElse (eager) String value3 = emptyOptional.orElse(fallbackSupplier.get()); } }
此示例演示了带有 Optional 的 Supplier。fallbackSupplier 仅在 Optional 为空时执行。当回退创建成本较高时,使用 orElseGet 与 Supplier 比 orElse 更有效。
在 Stream.generate() 中使用 Supplier
Stream.generate() 方法接受一个 Supplier 来创建无限流。这对于生成值序列非常有用,其中每个值都由 Supplier 产生。
package com.zetcode; import java.util.stream.Stream; import java.util.function.Supplier; import java.util.concurrent.ThreadLocalRandom; import java.util.List; import java.util.stream.Collectors; public class Main { public static void main(String[] args) { // Supplier for random doubles between 0 and 1 Supplier<Double> randomSupplier = () -> ThreadLocalRandom.current().nextDouble(); // Generate infinite stream of random numbers List<Double> randoms = Stream.generate(randomSupplier) .limit(5) .collect(Collectors.toList()); System.out.println("Random numbers: " + randoms); // Supplier for sequence numbers Supplier<Integer> sequenceSupplier = new Supplier<>() { private int next = 0; @Override public Integer get() { return next++; } }; List<Integer> sequence = Stream.generate(sequenceSupplier) .limit(5) .collect(Collectors.toList()); System.out.println("Sequence: " + sequence); } }
此示例显示了与 Stream.generate() 一起使用的 Supplier。randomSupplier 生成随机数,而 sequenceSupplier 维护状态以生成序列。两者都演示了无限流生成功能。
使用 Supplier 进行记忆化
Supplier 可用于实现记忆化——缓存昂贵计算的结果并在后续调用中返回它。此模式优化了性能。
package com.zetcode; import java.util.function.Supplier; public class Main { public static void main(String[] args) { // Expensive computation simulation Supplier<String> expensiveSupplier = () -> { System.out.println("Performing expensive computation..."); try { Thread.sleep(1000); // Simulate work } catch (InterruptedException e) { Thread.currentThread().interrupt(); } return "Computed Result"; }; // Memoizing supplier Supplier<String> memoizedSupplier = new Supplier<>() { private String value; @Override public String get() { if (value == null) { value = expensiveSupplier.get(); } return value; } }; System.out.println("First call (computes): " + memoizedSupplier.get()); System.out.println("Second call (cached): " + memoizedSupplier.get()); } }
此示例演示了使用 Supplier 进行记忆化。昂贵的计算仅在第一次 get() 调用时发生。后续调用返回缓存值。此模式对于产生相同结果的昂贵操作非常有用。
专用 Supplier
Java 为原始类型提供了专用的 Supplier 变体,以避免装箱开销。这些包括 BooleanSupplier、IntSupplier、LongSupplier 和 DoubleSupplier。
package com.zetcode; import java.util.function.*; public class Main { public static void main(String[] args) { // BooleanSupplier example BooleanSupplier booleanSupplier = () -> Math.random() > 0.5; System.out.println("Random boolean: " + booleanSupplier.getAsBoolean()); // IntSupplier example IntSupplier intSupplier = () -> (int) (Math.random() * 100); System.out.println("Random int: " + intSupplier.getAsInt()); // LongSupplier example LongSupplier longSupplier = System::currentTimeMillis; System.out.println("Current time: " + longSupplier.getAsLong()); // DoubleSupplier example DoubleSupplier doubleSupplier = Math::random; System.out.println("Random double: " + doubleSupplier.getAsDouble()); } }
此示例显示了专用的 Supplier 接口。每个接口都避免了其原始类型的装箱开销。它们遵循与通用 Supplier 相同的模式,但具有特定于类型的 get 方法(getAsBoolean、getAsInt 等)。
来源
在本文中,我们介绍了 Java Supplier 接口的基本方法和功能。理解这些概念对于 Java 应用程序中的函数式编程和高效的值生成至关重要。
作者
列出所有Java教程。