外行的 Java 8 供应商和消费者解释
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/28417262/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java 8 Supplier & Consumer explanation for the layperson
提问by james emanon
As a non-Java programmer learning Java, I am reading about Supplier
and Consumer
interfaces at the moment. And I can't wrap my head around their usage and meaning. When and why you would use these interfaces? Can someone give me a simple layperson example of this… I'm finding the Doc examples not succinct enough for my understanding.
作为一名学习 Java 的非 Java 程序员,我目前正在阅读Supplier
和Consumer
接口。我无法理解它们的用法和含义。何时以及为何使用这些接口?有人能给我一个简单的外行例子吗……我发现 Doc 的例子不够简洁,不足以让我理解。
采纳答案by Rohit Jain
This is Supplier:
这是供应商:
public Integer getInteger() {
return new Random().nextInt();
}
This is Consumer:
这是消费者:
public void sum(Integer a, Integer b) {
System.out.println(a + b);
}
So in layman terms, a supplier is a method that returns some value (as in it's return value). Whereas, a consumer is a method that consumes some value (as in method argument), and does some operations on them.
因此,通俗地说,供应商是一种返回某些值的方法(就像它的返回值一样)。而消费者是一种方法,它消耗一些值(如方法参数),并对它们进行一些操作。
Those will transform to something like these:
那些会变成这样的:
// 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);
As for usage, the very basic example would be: Stream#forEach(Consumer)
method. It takes a Consumer, which consumes the element from the stream you're iterating upon, and performs some action on each of them. Probably print them.
至于用法,非常基本的例子是:Stream#forEach(Consumer)
方法。它需要一个消费者,它消耗您正在迭代的流中的元素,并对它们中的每一个执行一些操作。可能打印出来。
Consumer<String> stringConsumer = (s) -> System.out.println(s.length());
Arrays.asList("ab", "abc", "a", "abcd").stream().forEach(stringConsumer);
回答by Stuart Marks
The reason you're having difficulty grasping the meaning of functional interfaces such as those in java.util.function
is that the interfaces defined here do not have any meaning! They are present primarily to represent structure, not semantics.
您难以理解函数式接口(例如 中的那些)的含义的原因是java.util.function
这里定义的接口没有任何意义!它们的存在主要是为了表示结构,而不是语义。
This is atypical for most Java APIs. The typical Java API, such as a class or interface, has meaning, and you can develop a mental model for what it represents and use that to understand the operations on it. Consider java.util.List
for example. A List
is a container of other objects. They have a sequence and an index. The number of objects contained in the list is returned by size()
. Each object has an index in the range 0..size-1 (inclusive). The object at index ican be retrieved by calling list.get(i)
. And so forth.
这对于大多数 Java API 来说是不典型的。典型的 Java API(例如类或接口)是有意义的,您可以为它所代表的内容开发一个心智模型,并使用它来理解对它的操作。考虑java.util.List
为例。AList
是其他对象的容器。它们有一个序列和一个索引。列表中包含的对象数由 返回size()
。每个对象都有一个范围为 0..size-1(含)的索引。可以通过调用 检索索引i处的对象list.get(i)
。等等。
The functional interfaces in java.util.function
don't have any such meaning. Instead, they're interfaces that merely represent the structureof a function, such as the number of arguments, the number of return values, and (sometimes) whether an argument or return value is a primitive. Thus we have something like Function<T,R>
which represents a function that takes a single argument of type Tand returns a value of type R. That's it. What does that function do? Well, it can do anything ... as long as it takes a single argument and returns a single value. That's why the specification for Function<T,R>
is little more than "Represents a function that accepts one argument and produces a result."
中的功能接口java.util.function
没有任何这样的含义。相反,它们是仅表示函数结构的接口,例如参数的数量、返回值的数量以及(有时)参数或返回值是否是原始值。因此,我们有类似的东西Function<T,R>
,它表示一个函数,它接受一个类型为T 的参数并返回一个类型为R的值。就是这样。这个函数有什么作用?嗯,它可以做任何事情……只要它接受一个参数并返回一个值。这就是为什么规范Function<T,R>
只是“表示一个接受一个参数并产生一个结果的函数”。
Clearly, when we're writing code, it has meaning, and that meaning has to come from somewhere. In the case of the functional interfaces, the meaning comes from the context in which they're used. The interface Function<T,R>
has no meaning in isolation. However, in the java.util.Map<K,V>
API, there is the following:
显然,当我们编写代码时,它是有意义的,而这种意义必须来自某个地方。在功能接口的情况下,含义来自使用它们的上下文。Function<T,R>
孤立的接口没有任何意义。但是,在java.util.Map<K,V>
API 中,有以下内容:
V computeIfAbsent(K key, Function<K,V> mappingFunction)
(wildcards elided for brevity)
(为简洁起见省略了通配符)
Ah, this use of Function
is as a "mapping function". What does that do? In this context, if key
is not already present in the map, the mapping function is called and is handed the key and is expected to produce a value, and the resulting key-value pair is inserted into the map.
啊,这个用法Function
是作为“映射函数”。那有什么作用?在这种情况下,如果key
映射中尚未存在,则调用映射函数并传递键并期望生成一个值,并将生成的键值对插入映射中。
So you can't look at the specification for Function
(or any of the other functional interfaces, for that matter) and attempt to discern what they mean. You have to look at where they're used in other APIs to understand what they mean, and that meaning applies only to that context.
因此,您无法查看Function
(或任何其他功能接口,就此而言)的规范并试图辨别它们的含义。您必须查看它们在其他 API 中的使用位置才能理解它们的含义,而该含义仅适用于该上下文。
回答by Steve K
A Supplier
is any method which takes no arguments and returns a value. Its job is literally to supply an instance of an expected class. For instance, every reference to a 'getter' method is a Supplier
ASupplier
是任何不带参数并返回值的方法。它的工作实际上是提供预期类的实例。例如,对“getter”方法的每个引用都是一个Supplier
public Integer getCount(){
return this.count;
}
Its instance method reference myClass::getCount
is an instance of Supplier<Integer>
.
它的实例方法引用myClass::getCount
是Supplier<Integer>
.
A Consumer
is any method which takes arguments and returns nothing. It is invoked for its side-effects. In Java terms, a Consumer
is an idiom for a void
method. 'setter' methods are a good example:
AConsumer
是任何接受参数但不返回任何内容的方法。它因其副作用而被调用。在 Java 术语中,aConsumer
是void
方法的惯用语。“setter”方法就是一个很好的例子:
public void setCount(int count){
this.count = count;
}
Its instance method reference myClass::setCount
is an instance of Consumer<Integer>
and IntConsumer
.
它的实例方法引用myClass::setCount
是Consumer<Integer>
and 的一个实例IntConsumer
。
A Function<A,B>
is any method which takes an argument of one type, and returns another. This can be referred to as a 'transformation'. The Function<A,B>
takes an A
and returns a B
. Notable is that for a given value of A
, the function should always return a specific value of B
. A
and B
can in fact be the same type, such as the following:
AFunction<A,B>
是接受一种类型的参数并返回另一种类型的任何方法。这可以称为“转换”。在Function<A,B>
接受一个A
和返回B
。值得注意的是,对于给定的 值A
,函数应始终返回特定的 值B
。A
并且B
实际上可以是相同的类型,例如:
public Integer addTwo(int i){
return i+2;
}
Its instance method reference myClass:addTwo
is a Function<Integer, Integer>
and a ToIntFunction<Integer>
.
它的实例方法引用myClass:addTwo
是 aFunction<Integer, Integer>
和 a ToIntFunction<Integer>
。
A Class method reference to a getter is another example of a function.
对 getter 的类方法引用是函数的另一个示例。
public Integer getCount(){
return this.count;
}
Its class method reference MyClass::getCount
is an instance of Function<MyClass,Integer>
and ToIntFunction<MyClass>
.
它的类方法引用MyClass::getCount
是Function<MyClass,Integer>
and 的一个实例ToIntFunction<MyClass>
。
回答by Dhruv Rai Puri
Why are Consumer/Supplier/other functional interfaces defined in java.util.function package: Consumer and Supplier are two, among many, of the in-built functional interfaces provided in Java 8. The purpose of all these in-built functional interfaces is to provide a ready "template" for functional interfaces having common function descriptors(functional method signatures/definitions).
为什么在 java.util.function 包中定义了消费者/供应商/其他功能接口:消费者和供应商是 Java 8 中提供的许多内置功能接口中的两个。所有这些内置功能接口的目的是为具有通用功能描述符(功能方法签名/定义)的功能接口提供现成的“模板”。
Lets say we have a required to convert a type T to another type R. If we were to pass anyfunction defined like this as a parameter to a method, then that method would need to define a Functional Interface whose functional/abstract method takes parameter of type T as input and gives a parameter of type R as output. Now, there could be many scenarios like this and the programmer(s) would end up defining multiple functional interfaces for their needs. To avoid this kind of a scenario, ease programming & bring a common standard in usage of functional interfaces, a set of in-built functional interfaces such as Predicate, Function, Consumer & Supplier have been defined.
假设我们需要将类型 T 转换为另一种类型 R。如果我们要将这样定义的任何函数作为参数传递给方法,那么该方法将需要定义一个函数接口,其函数/抽象方法接受参数类型 T 作为输入并给出 R 类型的参数作为输出。现在,可能有很多这样的场景,程序员最终会根据他们的需要定义多个功能接口。为了避免这种情况,简化编程并在功能接口的使用中引入通用标准,定义了一组内置的功能接口,例如 Predicate、Function、Consumer 和 Supplier。
What does Consumer do: Consumer functional interface accepts an input, does something with that input and does not give any output. Its definition is like this (from Java Source) -
消费者做什么:消费者功能接口接受一个输入,对该输入做一些事情并且不给出任何输出。它的定义是这样的(来自Java Source) -
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
}
Here accept() is the functional\abstract method which does takes an input and returns no output. So, if you want to input an Integer, do something with it with no output then instead of defining your own interface use an instance of Consumer.
这里的 accept() 是函数式\抽象方法,它接受一个输入并且不返回任何输出。所以,如果你想输入一个整数,用它做一些没有输出的事情然后而不是定义你自己的接口使用 Consumer 的实例。
What does Supplier do: Supplier functional interface does not take any input but returns an output. Its defined like this(from Java Source) -
供应商做什么:供应商功能接口不接受任何输入但返回输出。它是这样定义的(来自 Java Source) -
@FunctionalInterface
public interface Supplier<T> {
T get();
}
Wherever you need a function which returns something, say an Integer, but takes no output use an instance of Supplier.
无论你需要一个返回什么的函数,比如一个整数,但不接受输出,使用供应商的实例。
In case more clarity, along with example usage, of Consumer & Supplier interfaces is needed then you can refer my blog posts on the same - http://www.javabrahman.com/java-8/java-8-java-util-function-consumer-tutorial-with-examples/andhttp://www.javabrahman.com/java-8/java-8-java-util-function-supplier-tutorial-with-examples/
如果需要消费者和供应商接口的更清晰以及示例用法,那么您可以参考我的博客文章 - http://www.javabrahman.com/java-8/java-8-java-util- function-consumer-tutorial-with-examples/和http://www.javabrahman.com/java-8/java-8-java-util-function-supplier-tutorial-with-examples/
回答by lalitbhagtani
In Laymen terms,
用外行的话来说,
supplier will supply data but without consuming any data. In programming terms a method which doesn't take any argument but return a value. It is used to generate new values.
供应商将提供数据但不消耗任何数据。在编程术语中,一种不接受任何参数但返回值的方法。它用于生成新值。
http://codedestine.com/java-8-supplier-interface/
http://codedestine.com/java-8-supplier-interface/
consumer will consume data and but do not return any data. In programming terms a method which takes multiple argument and does not return any value.
消费者将消费数据,但不返回任何数据。在编程术语中,一种接受多个参数且不返回任何值的方法。
回答by Andrejs
1. Meaning
1. 意义
See my answers to my question hereand also another here, but in short these new Interfaces provide conventionand descriptivenessfor everyone to use (+ funky method chaining such as .forEach(someMethod().andThen(otherMethod()))
在这里查看我对我的问题的回答,也在这里查看另一个,但简而言之,这些新接口为每个人提供了约定和描述性(+ 时髦的方法链,例如.forEach(someMethod().andThen(otherMethod()))
2. Differences
2. 差异
Consumer: Takes something, does something, returns nothing: void accept(T t)
消费者:接受某事,做某事,不返回任何内容:void accept(T t)
Supplier:Takes nothing, returns something : T get()
(reverse of Consumer, basically a universal 'getter' method)
供应商:不采取任何措施,返回一些东西:( T get()
与消费者相反,基本上是一种通用的“getter”方法)
3. Usage
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);
Supplier: wrap repetitive code, e.g. code execution timing
供应商:包装重复代码,例如代码执行时间
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;
}
}
回答by Ankit Sood
Consumer and supplier are the interfaces provided by java. Consumer is use for iterate over the list elements and supplier is use for supply object's
消费者和供应商是java提供的接口。消费者用于迭代列表元素,供应商用于供应对象的
you can easily understand with code demonstration.
您可以通过代码演示轻松理解。
Consumer
消费者
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);
}
}
Supplier
供应商
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());
}
}