ZetCode

Java Supplier

最后修改时间:2024 年 3 月 5 日

在本文中,我们将展示如何在 Java 中使用 Supplier 函数式接口。

Supplier

Java Supplier 是一个函数式接口,表示返回结果的操作。Supplier 不接受任何参数。

一个 Supplier<T> 的设计目的是在不接受任何显式输入参数的情况下生成一个值。 它通过调用一个方法或在内部生成一个值来实现。

@FunctionalInterface
public interface Supplier<T> {

    T get();
}

T 是 supplier 提供的结果的类型。

Supplier 提供了一种简洁方便的方式来表示提供值的函数,从而促进 Java 中惰性求值、代码清晰性和与函数式编程概念的兼容性。

简单的 Supplier 示例

以下示例创建了一个简单的 supplier。

Main.java
void main() {

    var words = List.of("falcon", "cup", "fun", "cloud");

    var res = upperWords(words);
    System.out.println(res);
}

List<String> upperWords(List<String> words) {

    var uppered = new ArrayList<String>();

    for (var word : words) {

        Supplier<String> upperSupplier = word::toUpperCase;
        uppered.add(upperSupplier.get());
    }

    return uppered;
}

该程序使用 upperSupplier 将单词转换为大写。

Supplier<String> upperSupplier = word::toUpperCase;

Supplier 返回一个字符串。 它引用 String 类型的 toUpperCase 方法。 它可能看起来像 supplier 接受一个参数,但它不是;它接受对一个方法(该方法本身接受参数)的引用。

表达式 word::toUpperCase 指的是特定 word 实例上 toUpperCase 方法的绑定方法引用。 由于 word 是循环中的一个变量,因此为每个单词单独创建一个新的 Supplier<String>Supplier 上的 Supplier<String> 方法只需调用该特定捕获实例上的 toUpperCase

$ java Main.java
[FALCON, CUP, FUN, CLOUD]

产品 Supplier

下一个示例创建了一个返回产品的函数。

Main.java
Supplier<List<Product>> productSupplier = () -> {

    return List.of(
        new Product(1, "Product A"),
        new Product(2, "Product B"),
        new Product(3, "Product C"),
        new Product(4, "Product D"),
        new Product(5, "Product E"));
};

void main() {

    productSupplier.get().stream().limit(3).forEach(System.out::println);
}

record Product(int id, String name) {
}

定义的 supplier 返回一个产品列表。

productSupplier.get().stream().limit(3).forEach(System.out::println);

我们使用 get 检索列表。 我们将其转换为流并从列表中获取前三个产品。

$ java Main.java
Product[id=1, name=Product A]
Product[id=2, name=Product B]
Product[id=3, name=Product C]

IntSupplier

IntSupplier 表示 int 值结果的 supplier。 这是 Supplier 的 int 生成原始类型特化。

Main.java
void main() {

    IntSupplier randIntSupp = () -> new Random().nextInt(40);

    System.out.println(randIntSupp.getAsInt());
    System.out.println(randIntSupp.getAsInt());

    System.out.println("--------------------");

    IntStream.generate(randIntSupp).limit(6).forEach(System.out::println);
}

该程序创建了一个随机整数的 supplier。

IntSupplier randIntSupp = () -> new Random().nextInt(40);

IntSupplier 返回范围 [0,40) 内的随机整数。

System.out.println(randIntSupp.getAsInt());

我们使用 getAsInt 获取一个随机整数。

IntStream.generate(randIntSupp).limit(6).forEach(System.out::println);

生成了六个随机整数的流。

$ java Main.java
4
35
--------------------
31
4
10
30
15
8

斐波那契值 Supplier

下一个示例创建了一个生成斐波那契数列的 supplier。

Main.java
Supplier<Long> fibonacciSupplier = new Supplier<Long>() {

    long a = 0, b = 1;

    public Long get() {

        long nextValue = a + b;
        a = b;
        b = nextValue;
        return a;
    }
};

void main() {

    Stream<Long> fibs = Stream.generate(fibonacciSupplier);
    fibs.limit(20).forEach(e -> System.out.print(STR."\{e} "));
}

我们从斐波那契 supplier 创建一个流并获取前二十个值。

$ java Main.java
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 

CompletableFuture.supplyAsync

Supplier 接口用于各种 Java API 中。 例如,CompletableFuture.supplyAsync 返回一个异步完成的 CompletableFuture

Main.java
void main() throws ExecutionException, InterruptedException {

    CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            throw new IllegalStateException(e);
        }
        return new Random().nextInt(40);
    });

    System.out.println(future.get());
}

该程序在一个异步操作中返回范围 [0,40) 内的随机整数。

在本文中,我们使用了 Java Supplier 接口。

CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
    try {
        TimeUnit.SECONDS.sleep(1);
    } catch (InterruptedException e) {
        throw new IllegalStateException(e);
    }
    return new Random().nextInt(40);
});

CompletableFutureSupplier 作为参数。

来源

Java Supplier - 语言参考

在本文中,我们使用了 Supplier Java 接口。

作者

我的名字是 Jan Bodnar,我是一位充满热情的程序员,拥有丰富的编程经验。 我自 2007 年以来一直撰写编程文章。 迄今为止,我已经撰写了超过 1,400 篇文章和 8 本电子书。 我拥有超过十年的编程教学经验。

列出所有Java教程