您何时以及为何使用 Java 的供应商和消费者接口?
When and why would you use Java's Supplier and Consumer interfaces?
作为一名非 Java 程序员学习 Java,我目前正在阅读 Supplier
和 Consumer
接口。而且我无法理解它们的用法和含义。
您何时以及为何使用这些界面?有人可以给我一个简单的外行示例吗?
我发现 Doc 示例不够简洁,不足以让我理解。
这是供应商:
public Integer getInteger() {
return new Random().nextInt();
}
这是消费者:
public void sum(Integer a, Integer b) {
System.out.println(a + b);
}
因此,通俗地说,供应商是一种 return 具有某种价值(如其 return 价值)的方法。然而,消费者是一种消耗某些值(如方法参数)并对它们执行某些操作的方法。
那些将变成这样的东西:
// 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);
您之所以难以理解java.util.function
中的函数式接口的含义,是因为此处定义的接口没有任何意义!它们的存在主要是为了表示结构,而不是语义。
这对于大多数 Java API 来说是不典型的。典型的 Java API,例如 class 或接口,是有意义的,您可以为它所代表的内容开发一个心智模型,并使用它来理解对它的操作。以 java.util.List
为例。 List
是其他对象的容器。他们有一个序列和一个索引。列表中包含的对象数由 size()
编辑 return。每个对象都有一个在 0..size-1(含)范围内的索引。可以通过调用 list.get(i)
检索索引 i 处的对象。等等。
java.util.function
中的功能接口没有任何这样的含义。相反,它们是仅表示函数的 结构 的接口,例如参数的数量、return 值的数量,以及(有时)参数或return 值是原始值。因此我们有类似 Function<T,R>
的东西,它表示一个函数,它接受一个类型为 T 的参数和 returns 一个类型为 R[= 的值44=]。而已。该功能有什么作用?好吧,它可以做任何事情……只要它接受一个参数并且 returns 是一个值。这就是为什么 Function<T,R>
的规格比 "Represents a function that accepts one argument and produces a result."
显然,当我们编写代码时,它是有意义的,而这种意义必须来自某个地方。在功能接口的情况下,含义来自使用它们的上下文。接口 Function<T,R>
孤立地没有意义。但是,在java.util.Map<K,V>
API中,有如下内容:
V computeIfAbsent(K key, Function<K,V> mappingFunction)
(为简洁起见省略了通配符)
啊,这个 Function
的用法是 "mapping function"。那有什么作用?在这种情况下,如果 key
尚未出现在映射中,则调用映射函数并传递键并期望产生一个值,并将生成的键值对插入映射中。
因此您不能查看 Function
的规范(或任何其他功能接口,就此而言)并试图辨别它们的含义。您必须查看它们在其他 API 中的使用位置才能理解它们的含义,并且该含义仅适用于该上下文。
A Supplier
是任何不带参数且 return 有值的方法。它的工作实际上是提供预期 class 的实例。例如,每个对 'getter' 方法的引用都是 Supplier
public Integer getCount(){
return this.count;
}
它的实例方法引用myClass::getCount
是Supplier<Integer>
的一个实例。
A Consumer
是任何接受参数并且 return 什么都不带的方法。它因其副作用而被调用。在 Java 术语中,Consumer
是 void
方法的习语。 'setter' 方法就是一个很好的例子:
public void setCount(int count){
this.count = count;
}
它的实例方法引用myClass::setCount
是Consumer<Integer>
和IntConsumer
的实例。
A Function<A,B>
是接受一种类型参数和 return 另一种类型参数的任何方法。这可以称为'transformation'。 Function<A,B>
接受 A
,return 接受 B
。值得注意的是,对于给定的 A
值,函数应始终 return 特定的 B
值。 A
和B
其实可以是同一个类型,比如下面这样:
public Integer addTwo(int i){
return i+2;
}
它的实例方法引用myClass:addTwo
是一个Function<Integer, Integer>
和一个ToIntFunction<Integer>
.
对 getter 的 Class 方法引用是函数的另一个示例。
public Integer getCount(){
return this.count;
}
其class方法引用MyClass::getCount
是Function<MyClass,Integer>
和ToIntFunction<MyClass>
的一个实例。
为什么 Consumer/Supplier/other 函数接口定义在 java.util.function 包中 : 消费者和供应商是提供的许多内置函数接口中的两个在 Java 8. 所有这些内置功能接口的目的是为具有通用功能描述符(功能方法 signatures/definitions)的功能接口提供现成的 "template"。
假设我们需要将类型 T 转换为另一种类型 R。如果我们将这样定义的 any 函数作为参数传递给方法,那么方法需要定义一个功能接口,其 functional/abstract 方法将 T 类型的参数作为输入并给出 R 类型的参数作为输出。现在,可能有很多这样的场景,程序员最终会根据他们的需要定义多个功能接口。为了避免这种情况,简化编程并在功能接口的使用中引入通用标准,定义了一组内置功能接口,如谓词、函数、消费者和供应商。
Consumer 做什么:Consumer 功能接口接受一个输入,对该输入做一些事情并且不给出任何输出。它的定义是这样的(来自Java来源)-
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
}
这里的 accept() 是 functional\abstract 方法,它接受输入,returns 没有输出。所以,如果你想输入一个整数,用它做一些没有输出的事情,那么不要定义你自己的接口,而是使用消费者的实例。
Supplier 做什么:Supplier 功能接口不接受任何输入,但returns 输出。它的定义是这样的(来自 Java 来源)-
@FunctionalInterface
public interface Supplier<T> {
T get();
}
只要你需要一个 returns 东西的函数,比如说一个整数,但不使用供应商实例的输出。
如果需要更清晰的消费者和供应商接口以及示例用法,那么您可以参考我的博客文章 - http://www.javabrahman.com/java-8/java-8-java-util-function-consumer-tutorial-with-examples/ and http://www.javabrahman.com/java-8/java-8-java-util-function-supplier-tutorial-with-examples/
通俗地说,
供应商将提供数据但不消耗任何数据。在编程术语中,一种不接受任何参数但 return 值的方法。它用于生成新值。
http://codedestine.com/java-8-supplier-interface/
consumer 会消费数据但不会return任何数据。在编程术语中,一种方法采用多个参数并且不 return 任何值。
1。含义
查看我对问题 and also another 的回答,但简而言之,这些新界面为每个人提供了 约定 和 描述性 使用 (+ 时髦的方法链接,例如 .forEach(someMethod().andThen(otherMethod()))
2。差异
消费者:拿东西,做东西,returns什么都不做:void accept(T t)
供应商:什么都不拿,returns东西:T get()
(与消费者相反,基本上是通用的'getter'方法)
3。用法
// Consumer: It takes something (a String) and does something (prints it)
List<Person> personList = getPersons();
personList.stream()
.map(Person::getName)
.forEach(System.out::println);
供应商:包装重复代码,例如代码执行时间
public class SupplierExample {
public static void main(String[] args) {
// Imagine a class Calculate with some methods
Double result1 = timeMe(Calculate::doHeavyComputation);
Double result2 = timeMe(Calculate::doMoreComputation);
}
private static Double timeMe(Supplier<Double> code) {
Instant start = Instant.now();
// Supplier method .get() just invokes whatever it is passed
Double result = code.get();
Instant end = Instant.now();
Duration elapsed = Duration.between(start,end);
System.out.println("Computation took:" + elapsed.toMillis());
return result;
}
}
消费者和供应商是java提供的接口。消费者用于遍历列表元素,供应商用于供应对象的
通过代码演示,一目了然。
消费者
package com.java.java8;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
/**
* The Class ConsumerDemo.
*
* @author Ankit Sood Apr 20, 2017
*/
public class ConsumerDemo {
/**
* The main method.
*
* @param args
* the arguments
*/
public static void main(String[] args) {
List<String> str = new ArrayList<>();
str.add("DEMO");
str.add("DEMO2");
str.add("DEMO3");
/* Consumer is use for iterate over the List */
Consumer<String> consumer = new Consumer<String>() {
@Override
public void accept(String t) {
/* Print list element on consile */
System.out.println(t);
}
};
str.forEach(consumer);
}
}
供应商
package com.java.java8;
import java.util.function.Supplier;
/**
* The Class SupplierDemo.
*
* @author Ankit Sood Apr 20, 2017
*/
public class SupplierDemo {
/**
* The main method.
*
* @param args
* the arguments
*/
public static void main(String[] args) {
getValue(() -> "Output1");
getValue(() -> "OutPut2");
}
/**
* Gets the value.
*
* @param supplier
* the supplier
* @return the value
*/
public static void getValue(Supplier<?> supplier) {
System.out.println(supplier.get());
}
}
作为一名非 Java 程序员学习 Java,我目前正在阅读 Supplier
和 Consumer
接口。而且我无法理解它们的用法和含义。
您何时以及为何使用这些界面?有人可以给我一个简单的外行示例吗?
我发现 Doc 示例不够简洁,不足以让我理解。
这是供应商:
public Integer getInteger() {
return new Random().nextInt();
}
这是消费者:
public void sum(Integer a, Integer b) {
System.out.println(a + b);
}
因此,通俗地说,供应商是一种 return 具有某种价值(如其 return 价值)的方法。然而,消费者是一种消耗某些值(如方法参数)并对它们执行某些操作的方法。
那些将变成这样的东西:
// 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);
您之所以难以理解java.util.function
中的函数式接口的含义,是因为此处定义的接口没有任何意义!它们的存在主要是为了表示结构,而不是语义。
这对于大多数 Java API 来说是不典型的。典型的 Java API,例如 class 或接口,是有意义的,您可以为它所代表的内容开发一个心智模型,并使用它来理解对它的操作。以 java.util.List
为例。 List
是其他对象的容器。他们有一个序列和一个索引。列表中包含的对象数由 size()
编辑 return。每个对象都有一个在 0..size-1(含)范围内的索引。可以通过调用 list.get(i)
检索索引 i 处的对象。等等。
java.util.function
中的功能接口没有任何这样的含义。相反,它们是仅表示函数的 结构 的接口,例如参数的数量、return 值的数量,以及(有时)参数或return 值是原始值。因此我们有类似 Function<T,R>
的东西,它表示一个函数,它接受一个类型为 T 的参数和 returns 一个类型为 R[= 的值44=]。而已。该功能有什么作用?好吧,它可以做任何事情……只要它接受一个参数并且 returns 是一个值。这就是为什么 Function<T,R>
的规格比 "Represents a function that accepts one argument and produces a result."
显然,当我们编写代码时,它是有意义的,而这种意义必须来自某个地方。在功能接口的情况下,含义来自使用它们的上下文。接口 Function<T,R>
孤立地没有意义。但是,在java.util.Map<K,V>
API中,有如下内容:
V computeIfAbsent(K key, Function<K,V> mappingFunction)
(为简洁起见省略了通配符)
啊,这个 Function
的用法是 "mapping function"。那有什么作用?在这种情况下,如果 key
尚未出现在映射中,则调用映射函数并传递键并期望产生一个值,并将生成的键值对插入映射中。
因此您不能查看 Function
的规范(或任何其他功能接口,就此而言)并试图辨别它们的含义。您必须查看它们在其他 API 中的使用位置才能理解它们的含义,并且该含义仅适用于该上下文。
A Supplier
是任何不带参数且 return 有值的方法。它的工作实际上是提供预期 class 的实例。例如,每个对 'getter' 方法的引用都是 Supplier
public Integer getCount(){
return this.count;
}
它的实例方法引用myClass::getCount
是Supplier<Integer>
的一个实例。
A Consumer
是任何接受参数并且 return 什么都不带的方法。它因其副作用而被调用。在 Java 术语中,Consumer
是 void
方法的习语。 'setter' 方法就是一个很好的例子:
public void setCount(int count){
this.count = count;
}
它的实例方法引用myClass::setCount
是Consumer<Integer>
和IntConsumer
的实例。
A Function<A,B>
是接受一种类型参数和 return 另一种类型参数的任何方法。这可以称为'transformation'。 Function<A,B>
接受 A
,return 接受 B
。值得注意的是,对于给定的 A
值,函数应始终 return 特定的 B
值。 A
和B
其实可以是同一个类型,比如下面这样:
public Integer addTwo(int i){
return i+2;
}
它的实例方法引用myClass:addTwo
是一个Function<Integer, Integer>
和一个ToIntFunction<Integer>
.
对 getter 的 Class 方法引用是函数的另一个示例。
public Integer getCount(){
return this.count;
}
其class方法引用MyClass::getCount
是Function<MyClass,Integer>
和ToIntFunction<MyClass>
的一个实例。
为什么 Consumer/Supplier/other 函数接口定义在 java.util.function 包中 : 消费者和供应商是提供的许多内置函数接口中的两个在 Java 8. 所有这些内置功能接口的目的是为具有通用功能描述符(功能方法 signatures/definitions)的功能接口提供现成的 "template"。
假设我们需要将类型 T 转换为另一种类型 R。如果我们将这样定义的 any 函数作为参数传递给方法,那么方法需要定义一个功能接口,其 functional/abstract 方法将 T 类型的参数作为输入并给出 R 类型的参数作为输出。现在,可能有很多这样的场景,程序员最终会根据他们的需要定义多个功能接口。为了避免这种情况,简化编程并在功能接口的使用中引入通用标准,定义了一组内置功能接口,如谓词、函数、消费者和供应商。
Consumer 做什么:Consumer 功能接口接受一个输入,对该输入做一些事情并且不给出任何输出。它的定义是这样的(来自Java来源)-
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
}
这里的 accept() 是 functional\abstract 方法,它接受输入,returns 没有输出。所以,如果你想输入一个整数,用它做一些没有输出的事情,那么不要定义你自己的接口,而是使用消费者的实例。
Supplier 做什么:Supplier 功能接口不接受任何输入,但returns 输出。它的定义是这样的(来自 Java 来源)-
@FunctionalInterface
public interface Supplier<T> {
T get();
}
只要你需要一个 returns 东西的函数,比如说一个整数,但不使用供应商实例的输出。
如果需要更清晰的消费者和供应商接口以及示例用法,那么您可以参考我的博客文章 - http://www.javabrahman.com/java-8/java-8-java-util-function-consumer-tutorial-with-examples/ and http://www.javabrahman.com/java-8/java-8-java-util-function-supplier-tutorial-with-examples/
通俗地说,
供应商将提供数据但不消耗任何数据。在编程术语中,一种不接受任何参数但 return 值的方法。它用于生成新值。
http://codedestine.com/java-8-supplier-interface/
consumer 会消费数据但不会return任何数据。在编程术语中,一种方法采用多个参数并且不 return 任何值。
1。含义
查看我对问题 .forEach(someMethod().andThen(otherMethod()))
2。差异
消费者:拿东西,做东西,returns什么都不做:void accept(T t)
供应商:什么都不拿,returns东西:T get()
(与消费者相反,基本上是通用的'getter'方法)
3。用法
// Consumer: It takes something (a String) and does something (prints it)
List<Person> personList = getPersons();
personList.stream()
.map(Person::getName)
.forEach(System.out::println);
供应商:包装重复代码,例如代码执行时间
public class SupplierExample {
public static void main(String[] args) {
// Imagine a class Calculate with some methods
Double result1 = timeMe(Calculate::doHeavyComputation);
Double result2 = timeMe(Calculate::doMoreComputation);
}
private static Double timeMe(Supplier<Double> code) {
Instant start = Instant.now();
// Supplier method .get() just invokes whatever it is passed
Double result = code.get();
Instant end = Instant.now();
Duration elapsed = Duration.between(start,end);
System.out.println("Computation took:" + elapsed.toMillis());
return result;
}
}
消费者和供应商是java提供的接口。消费者用于遍历列表元素,供应商用于供应对象的
通过代码演示,一目了然。
消费者
package com.java.java8;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
/**
* The Class ConsumerDemo.
*
* @author Ankit Sood Apr 20, 2017
*/
public class ConsumerDemo {
/**
* The main method.
*
* @param args
* the arguments
*/
public static void main(String[] args) {
List<String> str = new ArrayList<>();
str.add("DEMO");
str.add("DEMO2");
str.add("DEMO3");
/* Consumer is use for iterate over the List */
Consumer<String> consumer = new Consumer<String>() {
@Override
public void accept(String t) {
/* Print list element on consile */
System.out.println(t);
}
};
str.forEach(consumer);
}
}
供应商
package com.java.java8;
import java.util.function.Supplier;
/**
* The Class SupplierDemo.
*
* @author Ankit Sood Apr 20, 2017
*/
public class SupplierDemo {
/**
* The main method.
*
* @param args
* the arguments
*/
public static void main(String[] args) {
getValue(() -> "Output1");
getValue(() -> "OutPut2");
}
/**
* Gets the value.
*
* @param supplier
* the supplier
* @return the value
*/
public static void getValue(Supplier<?> supplier) {
System.out.println(supplier.get());
}
}