Java 8 Supplier & Consumer explanation dla laika

Jako programista nie-Java uczący się Javy, czytam w tej chwili o interfejsach Supplier i Consumer. I nie mogę zawinąć głowy wokół ich użycia i znaczenia. Kiedy i dlaczego miałbyś używać tych interfejsów? Czy ktoś może mi podać prosty przykład laika ... uważam, że przykłady Doc nie są wystarczająco zwięzłe dla mojego zrozumienia.

 39
Author: jrtapsell, 2015-02-09

7 answers

To jest dostawca:

public Integer getInteger() {
    return new Random().nextInt();
}

To jest Konsument:

public void sum(Integer a, Integer b) {
    System.out.println(a + b);
}

Więc w kategoriach laika, dostawca jest metodą, która zwraca pewną wartość (jak w jego wartość zwracaną). Natomiast konsument to metoda, która zużywa pewną wartość (jak w argumencie metody) i wykonuje na nich pewne operacje.

Te przekształcą się w coś takiego:

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

Jeśli chodzi o użycie, podstawowym przykładem może być: Stream#forEach(Consumer) metoda. Zajmuje konsumenta, który konsumuje element z stream, na którym iterujesz, i wykonuje pewne działania na każdym z nich. Pewnie je wydrukują.

Consumer<String> stringConsumer = (s) -> System.out.println(s.length());
Arrays.asList("ab", "abc", "a", "abcd").stream().forEach(stringConsumer);
 48
Author: Rohit Jain,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-20 12:34:55

Powodem, dla którego masz trudności z pojęciem znaczenia funkcjonalnych interfejsów, takich jak te w java.util.function jest to, że interfejsy zdefiniowane tutaj nie mają żadnego znaczenia! Są one obecne przede wszystkim do reprezentowania struktury, A Nie semantyki.

Jest to nietypowe dla większości interfejsów API Javy. Typowe API Javy, takie jak klasa lub interfejs, ma znaczenie i można opracować mentalny model tego, co reprezentuje i użyć go do zrozumienia operacji na nim. Rozważ Na przykład. A List jest kontenerem innych obiektów. Mają sekwencję i indeks. Liczba obiektów znajdujących się na liście jest zwracana przez size(). Każdy obiekt ma indeks w zakresie 0..Rozmiar - 1 (włącznie). Obiekt o indeksie i {[16] } może być odzyskany przez wywołanie list.get(i). I tak dalej.

Interfejsy funkcjonalne w java.util.function nie mają takiego znaczenia. Zamiast tego są to interfejsy, które reprezentują jedynie strukturę funkcji, taką jak liczba argumenty, liczba zwracanych wartości i (czasami) to, czy argument lub wartość zwracana jest prymitywna. Tak więc mamy coś w rodzaju Function<T,R>, które reprezentuje funkcję, która pobiera pojedynczy argument typu T i zwraca wartość typu R . To wszystko. Do czego służy ta funkcja? Może zrobić wszystko ... tak długo, jak pobiera pojedynczy argument i zwraca pojedynczą wartość. Dlatego Specyfikacja Function<T,R> jest niewiele większa niż " reprezentuje funkcję, która przyjmuje jedną argument i daje wynik."

Oczywiście, kiedy piszemy kod, ma on znaczenie i to znaczenie musi skądś pochodzić. W przypadku interfejsów funkcjonalnych znaczenie pochodzi z kontekstu, w którym są używane. Interfejs Function<T,R> nie ma żadnego znaczenia w izolacji. Jednak w API java.util.Map<K,V> znajduje się:

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

(wildcards)

Ah, to użycie {[11] } jest "funkcją mapowania". Co to robi? W tym kontekście, jeśli key nie jest już obecny na mapie, funkcja mapowania jest wywoływana i przekazywana kluczowi i oczekuje się, że wytworzy wartość, a wynikowa para klucz-wartość jest wstawiana do mapy.

Nie można więc patrzeć na specyfikację Function (ani na żaden inny funkcjonalny interfejs) i próbować rozeznać, co one oznaczają. Aby zrozumieć, co oznaczają, musisz przyjrzeć się, gdzie są one używane w innych interfejsach API, a to znaczenie odnosi się tylko do tego kontekstu.

 90
Author: Stuart Marks,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-10 00:54:10

A {[4] } jest dowolną metodą, która nie pobiera argumentów i zwraca wartość. Jego zadaniem jest dosłownie dostarczenie instancji oczekiwanej klasy. Na przykład, każde odniesienie do metody "getter" jest Supplier

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

Jego odniesienie do metody instancji myClass::getCount jest instancją Supplier<Integer>.

A Consumer jest dowolną metodą, która pobiera argumenty i nie zwraca niczego. Jest wywoływany ze względu na skutki uboczne. W języku Java, a Consumer jest idiomem dla metody void. metody "settera" są dobrym przykład:

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

Jego odwołanie do metody instancji myClass::setCount jest instancją Consumer<Integer> i IntConsumer.

A {[14] } jest dowolną metodą, która pobiera argument jednego typu i zwraca inny. Można to nazwać "transformacją". Function<A,B> pobiera A i zwraca B. Warto zauważyć, że dla danej wartości A, funkcja powinna zawsze zwracać określoną wartość B. A i B w rzeczywistości mogą być tego samego typu, na przykład:

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

A Klasa odwołanie metody do gettera jest również funkcją.

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

Jego odniesienie do metody klasy MyClass::getCount jest instancją Function<MyClass,Integer> i ToIntFunction<MyClass>.

 18
Author: Steve K,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-12 23:11:47

Dlaczego w Javie zdefiniowane są Interfejsy funkcjonalne typu Consumer/Supplier/other.util.function package : Consumer i Supplier to dwa spośród wielu wbudowanych interfejsów funkcjonalnych w Javie 8. Celem wszystkich tych wbudowanych interfejsów funkcjonalnych jest dostarczenie gotowego "szablonu" dla interfejsów funkcjonalnych posiadających wspólne deskryptory funkcji(podpisy/definicje metod funkcjonalnych).

Powiedzmy, że mamy wymagane do konwersji typu T na inny typ R. Jeśli przekazać dowolną funkcję zdefiniowaną w ten sposób jako parametr do metody, wtedy ta metoda będzie musiała zdefiniować interfejs funkcjonalny, którego funkcjonalna / abstrakcyjna metoda przyjmuje parametr typu T jako wejście i daje parametr typu R jako wyjście. Teraz, nie może być wiele scenariuszy takich jak ten i programista(s) skończy się definiowanie wielu funkcjonalnych interfejsów dla swoich potrzeb. Aby uniknąć tego rodzaju scenariusza, łatwość programowania i wprowadzenie wspólnego standardu w użyciu interfejsów funkcjonalnych, a zdefiniowano zestaw wbudowanych interfejsów funkcjonalnych, takich jak predykat, funkcja, konsument I Dostawca.

Co robi konsument : funkcjonalny interfejs konsumenta akceptuje wejście, robi coś z tym wejściem i nie daje żadnego wyjścia. Jego definicja jest taka (ze źródła Java) -

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

Tutaj accept() jest metodą funkcyjną \ abstrakcyjną, która pobiera dane wejściowe i nie zwraca żadnych danych wyjściowych. Tak więc, jeśli chcesz wprowadzić liczbę całkowitą, zrób coś z nią bez wyjścia następnie zamiast definiować własny interfejs użyj instancji Consumer.

Co robi dostawca: Interfejs funkcjonalny dostawcy nie pobiera żadnych danych wejściowych, ale zwraca dane wyjściowe. Its defined like this (from Java Source) -

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

Gdziekolwiek potrzebujesz funkcji, która coś zwraca, powiedzmy liczbę całkowitą, ale nie pobiera danych wyjściowych, użyj instancji Supplier.

W przypadku, gdy potrzeba większej jasności, wraz z przykładowym użyciem, interfejsów konsumentów i Dostawców, możesz odnieść się do moje wpisy na blogu o tym samym - http://www.javabrahman.com/java-8/java-8-java-util-function-consumer-tutorial-with-examples/ oraz http://www.javabrahman.com/java-8/java-8-java-util-function-supplier-tutorial-with-examples/

 7
Author: Dhruv Rai Puri,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-09 10:37:49

1. Znaczenie

Zobacz moje odpowiedzi na moje pytanie tutaj, a także inne tutaj, ale w skrócie te nowe interfejsy zapewniają konwencję i opisowość dla każdego do użycia (+funky metody łańcuchowania, takie jak .forEach(someMethod().andThen(otherMethod()))

2. Różnice

Konsument : bierze coś, robi coś, nic nie zwraca: void accept(T t)

Dostawca: nic nie bierze, coś zwraca: T get() (odwrotność konsumenta, w zasadzie uniwersalna metoda "getter")

3. Użycie

// Consumer: It takes something (a String) and does something (prints it) 
    List<Person> personList = getPersons();

     personList.stream()
                    .map(Person::getName)    
                    .forEach(System.out::println); 

Dostawca: zawiń powtarzalny kod, np. czas wykonania kodu

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
Author: Andrejs,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 10:31:25

W kategoriach laików,

Dostawca dostarczy dane, ale bez konsumowania żadnych danych. W terminach programistycznych metoda, która nie przyjmuje żadnego argumentu, ale zwraca wartość. Służy do generowania nowych wartości.

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

Konsument konsumuje Dane i nie zwraca żadnych danych. W terminologii programowej metoda, która pobiera wiele argumentów i nie zwraca żadnej wartości.

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

 -1
Author: lalitbhagtani,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-07 11:47:30

Consumer i supplier to Interfejsy dostarczane przez Javę. Consumer is use for iterate over the list elements and supplier is use for supply object ' s

Możesz łatwo zrozumieć dzięki demonstracji kodu.

Consumer

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

    }

}

Dostawca

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

}
 -1
Author: Ankit Sood,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-20 07:21:37