Java 爪哇8供应商及;消费者对非专业人士的解释

Java 爪哇8供应商及;消费者对非专业人士的解释,java,java-8,Java,Java 8,作为一名学习Java的非Java程序员,我目前正在阅读有关供应商和消费者接口的书籍。我无法理解它们的用法和意义。何时以及为什么要使用这些接口?有人能给我一个简单的外行示例吗……我发现文档示例不够简洁,无法理解。这是供应商: public Integer getInteger() { return new Random().nextInt(); } 这是消费者: public void sum(Integer a, Integer b) { System.out.println(

作为一名学习Java的非Java程序员,我目前正在阅读有关
供应商
消费者
接口的书籍。我无法理解它们的用法和意义。何时以及为什么要使用这些接口?有人能给我一个简单的外行示例吗……我发现文档示例不够简洁,无法理解。

这是供应商:

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);

您很难理解功能接口(如
java.util.function
中的接口)的含义的原因是这里定义的接口没有任何意义!它们的出现主要是为了表示结构,而不是语义

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

java.util.function
中的函数接口没有这样的含义。相反,它们只是表示函数结构的接口,例如参数的数量、返回值的数量,以及(有时)参数或返回值是否为原语。因此,我们有类似于
函数的东西,它表示一个函数,它接受一个类型为T的参数,并返回一个类型为R的值。就是这样。这个函数做什么?嗯,它可以做任何事。。。只要它接受一个参数并返回一个值。这就是为什么
函数
的规范只不过是“表示接受一个参数并生成结果的函数”

显然,当我们编写代码时,它是有意义的,而这种意义必须来自某个地方。在功能接口的情况下,其含义来自使用它们的上下文。界面
功能
单独没有意义。但是,在
java.util.Map
API中,有以下内容:

V computeIfAbsent(K key, Function<K,V> mappingFunction)
public Integer addTwo(int i){
    return i+2;
}
V computeIfAbsent(K键,函数映射函数)
(为简洁起见,省略了通配符)

啊,这个
函数的使用是作为一个“映射函数”。那有什么用?在此上下文中,如果映射中尚未出现
key
,则调用映射函数并将其交给键,并期望生成一个值,然后将生成的键值对插入映射中


因此,您不能查看
函数
(或任何其他函数接口)的规范,试图辨别它们的含义。您必须查看它们在其他API中的使用位置,才能理解它们的含义,而这一含义仅适用于该上下文。

A
Supplier
是任何不带参数并返回值的方法。它的工作就是提供一个预期类的实例。例如,每个对“getter”方法的引用都是供应商

public Integer getCount(){
    return this.count;
}
它的实例方法reference
myClass::getCount
Supplier
的实例

使用者
是任何接受参数但不返回任何内容的方法。它因其副作用而被调用。在Java术语中,
Consumer
void
方法的习惯用法setter方法就是一个很好的例子:

public void setCount(int count){
    this.count = count;
}
其实例方法引用
myClass::setCount
Consumer
IntConsumer
的实例

函数
是接受一种类型的参数并返回另一种类型参数的任何方法。这可以称为“转换”。
函数
接受一个
A
并返回一个
B
。值得注意的是,对于给定的
a
,函数应始终返回
B
的特定值
A
B
实际上可以是相同的类型,例如:

V computeIfAbsent(K key, Function<K,V> mappingFunction)
public Integer addTwo(int i){
    return i+2;
}
它的实例方法reference
myClass:addTwo
是一个
函数
和一个
ToIntFunction

对getter的类方法引用是函数的另一个示例

public Integer getCount(){
    return this.count;
}

它的类方法引用
MyClass::getCount
函数
ToIntFunction
的一个实例

为什么消费者/供应商/其他功能接口在java.util.Function包中定义:消费者和供应商是众多接口中的两个,Java 8中提供的内置功能接口。所有这些内置功能接口的目的是为具有公共功能描述符(功能方法签名/定义)的功能接口提供一个现成的“模板”

假设我们需要将一个类型T转换为另一个类型R。如果我们要将这样定义的任何函数作为参数传递给一个方法,那么该方法将需要定义一个函数接口,其函数/抽象方法将类型T的参数作为输入,并将类型R的参数作为输出。现在,可能会有很多这样的场景,程序员最终会为他们的需求定义多个功能接口。为了避免这种情况,简化编程并在功能接口的使用中引入通用标准,定义了一组内置功能接口,如谓词、函数、消费者和供应商

@FunctionalInterface
public interface Supplier<T> {
  T get();
}
// 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);

    }

}
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());
    }

}