Java 8供应商和消费者对外行的解释

jam*_*non 75 java java-8

作为一名学习Java的非Java程序员,我正在阅读SupplierConsumer接口.我无法围绕他们的用法和意义.您何时以及为何使用这些界面?有人可以给我一个简单的非专业人士的例子......我发现Doc的例子不够简洁,我的理解.

Stu*_*rks 155

你在掌握功能接口的意义方面遇到困难的原因是java.util.function这里定义的接口没有任何意义!它们主要用于表示结构,而不是语义.

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

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

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

V computeIfAbsent(K key, Function<K,V> mappingFunction)
Run Code Online (Sandbox Code Playgroud)

(为简洁而省略了通配符)

啊,这个用途Function是作为"映射函数".那是做什么的?在此上下文中,如果key映射中尚未存在,则调用映射函数并将其传递给密钥,并期望生成一个值,并将生成的键值对插入到映射中.

因此,您无法查看Function(或任何其他功能接口)的规范,并试图辨别它们的含义.您必须查看它们在其他API中的用途,以了解它们的含义,并且该含义仅适用于该上下文.

  • 这是我要找的解释,谢谢! (4认同)
  • 所以基本上,它只是作为类型的功能 (3认同)

Roh*_*ain 79

这是供应商:

public Integer getInteger() {
    return new Random().nextInt();
}
Run Code Online (Sandbox Code Playgroud)

这是消费者:

public void sum(Integer a, Integer b) {
    System.out.println(a + b);
}
Run Code Online (Sandbox Code Playgroud)

因此,在外行人看来,供应商是一种返回某些价值的方法(如同它的回报价值).而消费者是一种消耗某些价值的方法(如方法参数),并对它们进行一些操作.

那些会变成这样的东西:

// 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);
Run Code Online (Sandbox Code Playgroud)

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

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

  • 这有什么好处而不是直接调用方法?是因为供应商可以像中间人那样行事并交出"回报"价值吗? (12认同)
  • 但为什么要创建这样一个结构呢?用 Java 来解决什么问题? (4认同)
  • 那么,供应商是一种创建返回"某事物"的方法实例的方法吗? (3认同)
  • @jamesemanon完全正确.这可能是方法参考,或lambda. (3认同)
  • Consumer&lt;Integer, Integer&gt; 无效。消费者有一个单一的类型参数。 (2认同)

Ste*_*e K 25

A Supplier是任何不带参数并返回值的方法.它的工作实际上是提供一个预期类的实例.例如,每个对'getter'方法的引用都是aSupplier

public Integer getCount(){
    return this.count;
}
Run Code Online (Sandbox Code Playgroud)

它的实例方法引用myClass::getCount是一个实例Supplier<Integer>.

A Consumer是任何接受参数并且不返回任何内容的方法.它的副作用被调用.在Java术语中,a Consumervoid方法的习惯用语.'setter'方法就是一个很好的例子:

public void setCount(int count){
    this.count = count;
}
Run Code Online (Sandbox Code Playgroud)

它的实例方法的参考myClass::setCount是的一个实例Consumer<Integer>IntConsumer.

A Function<A,B>是采用一种类型的参数并返回另一种类型的任何方法.这可以称为"转换".在Function<A,B>接受一个A和返回B.值得注意的是,对于给定值A,函数应始终返回特定值B.A并且B实际上可以是相同的类型,例如以下内容:

public Integer addTwo(int i){
    return i+2;
}
Run Code Online (Sandbox Code Playgroud)

对getter的Class方法引用也是一个函数.

public Integer getCount(){
    return this.count;
}
Run Code Online (Sandbox Code Playgroud)

其类方法参考myClass:addTwo是的一个实例Function<Integer, Integer>ToIntFunction<Integer>.


Dhr*_*uri 11

为什么java.util.function包中定义的消费者/供应商/其他功能接口:消费者和供应商是Java 8中提供的内置功能接口中的两个.所有这些内置功能接口的目的是为具有共同功能描述符(功能方法签名/定义)的功能接口提供准备好的"模板".

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

消费者做什么:消费者功能接口接受输入,对该输入做某事并且不给出任何输出.它的定义是这样的(来自Java Source) -

@FunctionalInterface
public interface Consumer<T> {
 void accept(T t);
}
Run Code Online (Sandbox Code Playgroud)

这里accept()是一个函数\ abstract方法,它接受输入并且不返回任何输出.因此,如果你想输入一个Integer,用它做一些没有输出的东西,那么使用Consumer的一个实例而不是定义你自己的接口.

供应商做什么:供应商功能界面不接受任何输入但返回输出.它定义如下(来自Java Source) -

@FunctionalInterface
public interface Supplier<T> {
  T get();
}
Run Code Online (Sandbox Code Playgroud)

只要你需要一个返回某个东西的函数,比如一个Integer,但不使用输出,就使用一个Supplier实例.

如果需要更清晰,以及消费者和供应商界面的示例用法,那么您可以参考我的博客文章 - 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/


And*_*ejs 10

1.意义

在这里查看我的问题的答案以及此处的另一个问题,但简而言之,这些新的界面为每个人提供了约定描述性(+时髦的方法链接,如.forEach(someMethod().andThen(otherMethod()))

2.差异

消费者:做某事,做某事,什么都不回报:void accept(T t)

供应商: 什么都不做,退货:( T get()与消费者相反,基本上是一种普遍的'吸气'方式)

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); 
Run Code Online (Sandbox Code Playgroud)

供应商:包装重复代码,例如代码执行时间

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;
    }
}
Run Code Online (Sandbox Code Playgroud)