您何时以及为何会使用 Java 的供应商和消费者接口?

2022-08-31 08:25:34

作为一名学习Java的非Java程序员,我现在正在阅读和接口。我无法理解它们的用法和含义。SupplierConsumer

您何时以及为何会使用这些接口?有人能给我一个简单的外行例子吗?

我发现Doc示例不够简洁,无法理解。


答案 1

您难以掌握功能接口(例如其中的那些)的含义的原因是,此处定义的接口没有任何意义!它们主要是为了表示结构而存在的,而不是语义。java.util.function

对于大多数Java API来说,这是非典型的。典型的Java API(例如类或接口)具有意义,您可以为它所表示的内容开发一个心智模型,并使用它来理解对其上的操作。例如,考虑一下。A 是其他对象的容器。它们有一个序列和一个索引。列表中包含的对象数由 返回。每个对象都有一个介于 0..size-1(包括 0..size-1)范围内的索引。索引 i 处的对象可以通过调用 来检索。等等。java.util.ListListsize()list.get(i)

中的功能接口没有任何这样的含义。相反,它们是仅表示函数结构的接口,例如参数数,返回值数以及(有时)参数或返回值是否为基元。因此,我们有类似的东西来表示一个函数,该函数采用T类型的单个参数并返回类型R的值。就是这样。该函数有什么作用?好吧,它可以做任何事情...只要它接受单个参数并返回单个值。这就是为什么 的规范只不过是“表示接受一个参数并产生结果的函数”。java.util.functionFunction<T,R>Function<T,R>

显然,当我们编写代码时,它有意义,而这种意义必须来自某个地方。在功能接口的情况下,含义来自使用它们的上下文。该接口在孤立的情况下没有任何意义。但是,在 API 中,存在以下内容:Function<T,R>java.util.Map<K,V>

V computeIfAbsent(K key, Function<K,V> mappingFunction)

(为简洁起见,省略了通配符)

呵呵,这个用法就是作为“映射函数”。这是做什么的?在此上下文中,如果映射中尚不存在映射函数,则调用映射函数并传递键并期望生成一个值,并将生成的键值对插入到映射中。Functionkey

因此,您无法查看规范(或任何其他功能接口,就此而言)并试图辨别它们的含义。您必须查看它们在其他API中的使用位置才能理解它们的含义,并且该含义仅适用于该上下文。Function


答案 2

这是供应商:

public Integer getInteger() {
    return new Random().nextInt();
}

这是消费者:

public void sum(Integer a, Integer b) {
    System.out.println(a + b);
}

因此,通俗地说,供应商是一种返回某些值的方法(如其返回值)。然而,使用者是一种消耗一些值的方法(如方法参数),并对其执行一些操作。

这些将转换为如下所示的内容:

// new operator itself is a supplier, of the reference to the newly created object
Supplier<List<String>> listSupplier = ArrayList::new;
Consumer<String> printConsumer = a1 -> System.out.println(a1);
BiConsumer<Integer, Integer> sumConsumer = (a1, a2) -> System.out.println(a1 + a2);

至于用法,最基本的例子是:Stream#forEach(Consumer)方法。它需要一个 Consumer,它使用您正在迭代的流中的元素,并对每个元素执行一些操作。可能打印它们。

Consumer<String> stringConsumer = (s) -> System.out.println(s.length());
Arrays.asList("ab", "abc", "a", "abcd").stream().forEach(stringConsumer);

推荐