Java 8 объяснение поставщика и потребителя для непрофессионала

как программист не-Java, изучающий Java, я читаю о Supplier и Consumer интерфейсов на данный момент. И я не могу разобраться в их значении. Когда и почему вы будете использовать эти интерфейсы? Может кто-нибудь дать мне простой пример непрофессионала этого... я нахожу примеры Doc недостаточно краткими для моего понимания.

7 ответов


Это поставщика:

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<String> stringConsumer = (s) -> System.out.println(s.length());
Arrays.asList("ab", "abc", "a", "abcd").stream().forEach(stringConsumer);

причина у вас возникли трудности с пониманием значения функциональных интерфейсов, таких как java.util.function то, что интерфейсы, определенные здесь, не имеют никакого значения! Они присутствуют прежде всего для представления структура, а не семантика.

это нетипично для большинства API Java. Типичный API Java, такой как класс или интерфейс, имеет значение, и вы можете разработать ментальную модель для того, что он представляет, и использовать это для понимания операции на нем. Считать java.util.List например. А List является контейнером для других объектов. У них есть последовательность и индекс. Количество объектов, содержащихся в списке, возвращается size(). Каждый объект имеет индекс в диапазоне 0..размер-1 (включительно). Объект по индексу я можно получить, позвонив 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)

(подстановочные знаки для краткость)

Ах, это использование Function является "функцией отображения". Что это значит? В этом контексте, если key еще не присутствует на карте, функция отображения вызывается и передается ключ и, как ожидается, произведет значение, и результирующая пара ключ-значение вставляется в карту.

поэтому вы не можете посмотреть спецификацию для Function (или любой другой функциональный интерфейс, если на то пошло) и попытаться понять, что они означают. Ты должен посмотрите, где они используются в других API, чтобы понять, что они означают, и это значение применимо только к этому контексту.


A Supplier - это любой метод, который не принимает никаких аргументов и возвращает значение. Его задача-буквально предоставить экземпляр ожидаемого класса. Например, каждая ссылка на метод "getter" является Supplier

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

ссылка на метод экземпляра myClass::getCount пример Supplier<Integer>.

A Consumer - это любой метод, который принимает аргументов и ничего не возвращает. Оно вызвано для своих побочных эффектов. В терминах Java a Consumer это идиома для void метод. хорошим примером являются методы "сеттера":

public void setCount(int count){
    this.count = count;
}

ссылка на метод экземпляра myClass::setCount пример Consumer<Integer> и IntConsumer.

A Function<A,B> - это любой метод, который принимает аргумент одного типа, и возвращает другое. Это можно назвать "трансформацией". The Function<A,B> принимает A и возвращает B. Примечательно, что для заданного значения A функция всегда должна возвращать значение B. A и B может на самом деле быть того же типа, например:

public Integer addTwo(int i){
    return i+2;
}

ссылка метода класса на геттер также является функцией.

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

ссылка на метод класса MyClass::getCount пример Function<MyClass,Integer> и ToIntFunction<MyClass>.


почему потребитель / поставщик / другие функциональные интерфейсы определены в java.утиль.пакет функций: потребитель и поставщик-это два, среди многих, встроенных функциональных интерфейса, предоставляемых в Java 8. Цель всех этих встроенных функциональных интерфейсов-предоставить готовый "шаблон" для функциональных интерфейсов, имеющих общие дескрипторы функций(сигнатуры/определения функциональных методов).

допустим, у нас есть необходимое для преобразования типа T в другой тип R. Если мы пройдем!--7-->любой функция, определенная как это в качестве параметра метода, тогда этот метод должен будет определить функциональный интерфейс, функциональный / абстрактный метод которого принимает параметр типа T в качестве входного и дает параметр типа R в качестве выходного. Теперь может быть много сценариев, подобных этому, и программист(ы) в конечном итоге определит несколько функциональных интерфейсов для своих нужд. Чтобы избежать такого сценария, простота программирования и общих стандартов в использовании определены функциональные интерфейсы, набор встроенных функциональных интерфейсов, таких как предикат, функция, потребитель и поставщик.

что делает потребитель: интерфейс потребителя функциональный принимает входной сигнал, делает что-то с этим входным сигналом и не дает никакой выход. Его определение похоже на это (из источника Java) -

@FunctionalInterface
public interface Consumer<T> {
 void accept(T t);
}

здесь accept () - это функциональный\абстрактный метод, который принимает вход и не возвращает вывода. Итак, если вы хотите ввести Integer, сделайте что-то с ним без вывода, а затем вместо определения собственного интерфейса используйте экземпляр Consumer.

что делает поставщик: интерфейс поставщика функциональный не принимает никакой входной сигнал но возвращает выход. Его определяется так(из источника Java) -

@FunctionalInterface
public interface Supplier<T> {
  T get();
}

везде, где вам нужна функция, которая возвращает что-то, скажем, целое число, но не выводит экземпляр поставщика.

в случае большей ясности, наряду с примерами использование интерфейсов потребителя и поставщика необходимо, тогда вы можете ссылаться на мои сообщения в блоге на то же самое - 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/


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

поставщик: оберните повторяющийся код, например, время выполнения кода

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

в непрофессиональных терминах,

поставщик будет поставлять данные, но не потребляя никаких данных. В терминах программирования Метод, который не принимает никаких аргументов, но возвращает значение. Он используется для генерации новых значений.

http://codedestine.com/java-8-supplier-interface/

потребитель будет потреблять информацию, но не возвращает никаких данных. С точки зрения программирования Метод, который принимает несколько аргументов и не возвращает никакого значения.

http://codedestine.com/java-8-consumer-interface/


потребитель и поставщик-это интерфейсы, предоставляемые 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());
    }

}