Подтвердить что ты не робот

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

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

4b9b3361

Ответ 1

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

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

Ответ 2

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

Это не типично для большинства API Java. Обычный Java API, такой как класс или интерфейс, имеет смысл, и вы можете разработать ментальную модель для того, что она представляет, и использовать ее для понимания операций на ней. Рассмотрим, например, java.util.List. A List - контейнер других объектов. У них есть последовательность и индекс. Количество объектов, содержащихся в списке, возвращается size(). Каждый объект имеет индекс в диапазоне 0..размер-1 (включительно). Объект с индексом я можно получить, вызвав list.get(i). И так далее.

Функциональные интерфейсы в java.util.function не имеют такого значения. Вместо этого они являются интерфейсами, которые просто представляют структуру функции, такую ​​как количество аргументов, количество возвращаемых значений и (иногда), является ли аргумент или возвращаемое значение примитивным. Таким образом, мы имеем что-то вроде Function<T,R>, которое представляет собой функцию, которая принимает один аргумент типа T и возвращает значение типа R. Это. Что делает эта функция? Ну, он может делать все... до тех пор, пока он принимает один аргумент и возвращает одно значение. Поэтому спецификация для Function<T,R> немного больше, чем "Представляет функцию, которая принимает один аргумент и производит результат".

Ясно, что когда мы пишем код, у него есть смысл, и этот смысл должен произойти откуда-то. В случае функциональных интерфейсов смысл исходит из контекста, в котором они используются. Интерфейс Function<T,R> не имеет смысла в изоляции. Однако в API java.util.Map<K,V> существует следующее:

V computeIfAbsent(K key, Function<K,V> mappingFunction)

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

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

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

Ответ 3

Supplier - это любой метод, который не принимает аргументов и возвращает значение. Его работа состоит в том, чтобы буквально предоставить экземпляр ожидаемого класса. Например, каждая ссылка на метод "получателя" является 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> - это любой метод, который принимает аргумент одного типа и возвращает другой. Это можно назвать "преобразованием". Function<A,B> принимает A и возвращает B Следует отметить, что для данного значения A функция всегда должна возвращать определенное значение B A и B на самом деле могут быть одного типа, такие как следующие:

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

Ссылка на метод экземпляра myClass:addTwo представляет собой Function<Integer, Integer> и функцию ToIntFunction<Integer>.

Ссылка на метод класса для получения является еще одним примером функции.

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

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

Ответ 4

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

Допустим, у нас есть требование для преобразования типа T в другой тип R. Если бы мы передали в метод любую функцию, определенную как этот параметр, то этот метод должен был бы определить функциональный интерфейс, чей функциональный/абстрактный метод принимает параметр типа T в качестве входных данных и дает параметр типа R в качестве выходных данных. Теперь таких сценариев может быть много, и программист в конечном итоге определит несколько функциональных интерфейсов для своих нужд. Чтобы избежать такого сценария, упростить программирование и ввести общий стандарт использования функциональных интерфейсов, был определен набор встроенных функциональных интерфейсов, таких как Predicate, Function, Consumer & Supplier.

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

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

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

Что делает Поставщик: Функциональный интерфейс Поставщика не принимает никаких входных данных, а возвращает выходные данные. Это определено так (из Java Source) -

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

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

В случае, если необходима дополнительная ясность, а также пример использования интерфейсов Consumer & Supplier, вы можете ссылаться на мои сообщения в блоге по этому же адресу - http://www.javabrahman.com/java-8/java-8-java-util- функция-потребитель-учебник с примерами / и http://www.javabrahman.com/java-8/java-8-java-util-function-supplier-tutorial-with-examples/

Ответ 5

1. Значение

Посмотрите мои ответы на мой вопрос здесь, а также еще один здесь, но вкратце эти новые интерфейсы предоставляют условное и описательность для всех, кто может использовать (+ funky method chaining, например .forEach(someMethod().andThen(otherMethod()))

2. Различия

Потребитель: принимает что-то, что-то делает, ничего не возвращает: void accept(T t)

Поставщик: ничего не принимает, возвращает что-то: T get() (обратная сторона Потребителя, в основном универсальный метод "getter" )

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

Ответ 6

Поставщик и потребитель - это функциональные интерфейсы (т.е. интерфейс с одним методом). Они были представлены на Java 8 наряду с другими конструкциями функционального программирования, используемыми для пакетной обработки потоков информации.

У поставщика есть один метод с именем get, который возвращает значение

// functional interface
public interface Supplier {
  // one method
  public void get();
}

У потребителя есть один метод с именем accept, который добавляет значение

// functional interface
public interface Consumer {
  // one method
  public void accept();
}

Пример, который реализует интерфейсы Поставщика и Потребителя:

import java.util.function.Supplier;
import java.util.function.Consumer;

public class SupplierConsumerExample {
  public static void main(String[] args) {


    Supplier<String> supplier = () -> {
      return "s1";
    };
    String s1 = supplier.get();
    System.out.println(s1); // output: "s1"


    Consumer<String> consumer = (c) -> {
      System.out.println(c); // output: "c1", "c2"
    };
    consumer.accept("c1");
    consumer.accept("c2");


  }    
}

Ответ 7

В терминах Laymen

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

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

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

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

Ответ 8

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

}