Как программист не-Java обучения Java, я читал о Supplier
и Consumer
интерфейсы в данный момент. И я не могу осмыслить их использование и значение. Когда и почему вы должны использовать эти интерфейсы? Может ли кто-нибудь дать мне простой пример для непрофессионала ... Я считаю, что примеры Doc недостаточно краткие для моего понимания.
103
Consumer
иSupplier
вы также можете выполнить поиск по руководству поConsumer
…Ответы:
Это поставщик:
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);
источник
Причина, по которой вам трудно понять значение функциональных интерфейсов, таких как те, что в
java.util.function
том, что интерфейсы, определенные здесь, не имеют никакого значения! Они представлены в первую очередь для представления структуры , а не семантики .Это нетипично для большинства API Java. Типичный Java API, такой как класс или интерфейс, имеет значение, и вы можете разработать мысленную модель того, что он представляет, и использовать ее для понимания операций с ней. Рассмотрим
java.util.List
для примера. AList
- это контейнер других объектов. У них есть последовательность и индекс. Количество объектов, содержащихся в списке, возвращаетсяsize()
. Каждый объект имеет индекс в диапазоне 0..размер-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)
(символы подстановки опущены для краткости)
Ах, это использование
Function
в качестве «функции отображения». Что это значит? В этом контексте, если онkey
еще не присутствует на карте, вызывается функция сопоставления, и ей передается ключ, и ожидается, что она выдаст значение, а полученная пара ключ-значение вставляется в карту.Таким образом, вы не можете смотреть на спецификацию
Function
(или любой другой функциональный интерфейс, если на то пошло) и пытаться понять, что они означают. Вы должны посмотреть, где они используются в других API, чтобы понять, что они означают, и это значение применимо только к этому контексту.источник
A
Supplier
- это любой метод, который не принимает аргументов и возвращает значение. Его работа буквально заключается в предоставлении экземпляра ожидаемого класса. Например, каждая ссылка на метод получения - этоSupplier
public Integer getCount(){ return this.count; }
Ссылка на его метод экземпляра
myClass::getCount
является экземпляромSupplier<Integer>
.A
Consumer
- это любой метод, который принимает аргументы и ничего не возвращает. Его вызывают из-за его побочных эффектов. В терминах Java aConsumer
- это идиома дляvoid
метода. Хорошим примером являются методы setter:public void setCount(int count){ this.count = count; }
Ссылка на его метод экземпляра
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; }
Ссылка на его метод экземпляра
myClass:addTwo
- это aFunction<Integer, Integer>
и aToIntFunction<Integer>
.Ссылка метода класса на получатель - еще один пример функции.
public Integer getCount(){ return this.count; }
Ссылка на его метод класса
MyClass::getCount
является экземпляромFunction<MyClass,Integer>
иToIntFunction<MyClass>
.источник
Почему в пакете java.util.function определены интерфейсы потребителя / поставщика / других функциональных интерфейсов : Потребитель и поставщик - это два, среди многих, встроенных функциональных интерфейсов, представленных в Java 8. Назначение всех этих встроенных функциональных интерфейсов - предоставить готовый «шаблон» для функциональных интерфейсов, имеющих общие дескрипторы функций (сигнатуры / определения функциональных методов).
Допустим, у нас есть требование для преобразования типа T в другой тип R. Если бы мы должны были передать любую функцию, определенную таким образом, как параметр методу, тогда этот метод должен был бы определить функциональный интерфейс, функциональный / абстрактный метод которого принимает параметр типа T в качестве входа и дает параметр типа R в качестве выхода. Таких сценариев может быть много, и программист (ы) в конечном итоге определит несколько функциональных интерфейсов для своих нужд. Чтобы избежать такого сценария, упростить программирование и ввести общий стандарт в использовании функциональных интерфейсов, был определен набор встроенных функциональных интерфейсов, таких как Predicate, Function, Consumer & Supplier.
Что делает потребитель : функциональный интерфейс потребителя принимает ввод, что-то делает с этим вводом и не выдает никакого вывода. Его определение выглядит так (из источника Java) -
@FunctionalInterface public interface Consumer<T> { void accept(T t); }
Здесь accept () - это функциональный \ абстрактный метод, который принимает входные данные и не возвращает выходных данных. Итак, если вы хотите ввести целое число, сделайте с ним что-нибудь без вывода, тогда вместо определения собственного интерфейса используйте экземпляр Consumer.
Что делает поставщик : функциональный интерфейс поставщика не принимает никаких входных данных, но возвращает выходные данные. Его определяют так (из источника Java) -
@FunctionalInterface public interface Supplier<T> { T get(); }
Везде, где вам нужна функция, которая что-то возвращает, скажем целое число, но не принимает никаких выходных данных, используйте экземпляр 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/
источник
1. Значение
См. Мои ответы на мой вопрос здесь, а также еще один здесь , но вкратце эти новые интерфейсы обеспечивают условность и наглядность для всех, чтобы их мог использовать (+ цепочка фанковых методов, например
.forEach(someMethod().andThen(otherMethod()))
2. Различия
Потребитель : что-то берет, что-то делает, ничего не возвращает:
void accept(T t)
Поставщик: ничего не берет, что-то возвращает:
T get()
(противоположность Consumer, в основном универсальный метод получения)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()); } }
источник
Самый простой ответ может быть таким:
Потребителя можно рассматривать как функцию <T, Void>. Поставщика можно рассматривать как функцию <Void, T>.
источник