何时以及为什么要使用这些接口?有人能给我一个简单易懂的例子吗?
我发现文档示例对我的理解不够简洁。
java.util.function
中的函数式接口这样的内容,是因为这里定义的接口没有任何含义!它们主要存在于表示结构,而不是语义。java.util.List
。列表是其他对象的容器。它们有一个序列和一个索引。列表中包含的对象数量由size()
返回。每个对象在0..size-1(包括)范围内都有一个索引。可以通过调用list.get(i)
来检索索引为i的对象。等等。
java.util.function
中的函数式接口没有这样的含义。相反,它们只是表示函数的结构的接口,例如参数的数量、返回值的数量以及(有时)参数或返回值是否为原始类型。因此我们有了像Function<T,R>
这样的东西,它表示一个接受类型为T的单个参数并返回类型为R的值的函数。就是这样。这个函数做什么?嗯,它可以做任何事情......只要它接受一个参数并返回一个值。这就是为什么Function<T,R>
的规范几乎只有“表示接受一个参数并产生结果的函数”。Function<T,R>
没有孤立的意义。然而,存在以下内容:V computeIfAbsent(K key, Function<K,V> mappingFunction)
(为了简洁起见,通配符已省略)
啊,这里使用的Function
是作为“映射函数”。那它是做什么用的呢?在这个上下文中,如果key
还没有出现在映射中,就会调用映射函数,并将key传递给它并期望它生成一个值,然后将生成的键值对插入到映射中。
因此,你不能查看Function
(或任何其他函数接口)的规范并试图理解它们的含义。你必须查看它们在其他API中的使用方式才能理解它们的含义,并且这个含义仅适用于该上下文。
这是供应商:
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);
Supplier
是指不接收参数并返回值的任何方法。它的工作就是提供预期类的实例。例如,每个'getter'方法的引用都是一个Supplier
public Integer getCount(){
return this.count;
}
它的实例方法引用 myClass::getCount
是一个 Supplier<Integer>
的实例。
Consumer
是任何接受参数且不返回值的方法。它被调用是由于其副作用。在Java术语中,Consumer
是指代 void
方法的惯用语法。'setter' 方法是一个很好的例子:
public void setCount(int count){
this.count = count;
}
它的实例方法引用 myClass::setCount
是一个 Consumer<Integer>
和 IntConsumer
的实例。
Function<A,B>
是一个接受一个类型为 A 的参数并返回另一个类型为 B 的任何方法。 这可以称为“转换”。Function<A,B>
接受 A
并返回 B
。值得注意的是,对于给定的 A
值,函数应始终返回特定的 B
值。实际上,A
和 B
可以是相同的类型,例如以下内容:
public Integer addTwo(int i){
return i+2;
}
它的实例方法引用 myClass:addTwo
是一个 Function<Integer, Integer>
和一个 ToIntFunction<Integer>
。
对于getter的类方法参考是另一个函数的示例。
public Integer getCount(){
return this.count;
}
它的类方法引用 MyClass::getCount
是一个 Function<MyClass,Integer>
和 ToIntFunction<MyClass>
的实例。
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
}
这里的accept()是一个功能性/抽象方法,它接受输入并不返回输出。因此,如果您想要输入一个整数,并对其进行处理而没有任何输出,则可以使用Consumer的实例,而不是定义自己的接口。
Supplier是做什么的:Supplier功能接口不接受任何输入,但返回一个输出。它的定义如下(来自Java源代码)-
@FunctionalInterface
public interface Supplier<T> {
T get();
}
请参考我在这里和另一个这里的答案,简而言之,这些新接口为每个人提供了惯例和描述性,以便使用(+时髦的方法链接,如.forEach(someMethod().andThen(otherMethod()))
)。
Consumer:接收某物,执行某些操作,不返回任何内容:void accept(T t)
Supplier:不接收任何内容,返回某物:T get()
(与Consumer相反,基本上是通用的“getter”方法)
// 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;
}
}
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());
}
}
http://codedestine.com/java-8-supplier-interface/
消费者将消耗数据,但不返回任何数据。在编程术语中,这是一个接受多个参数但不返回任何值的方法。
Consumer
和Supplier
的用法。您也可以在教程中搜索“Consumer”... - Holger