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教程。