जावा 8 आपूर्तिकर्ता और उपभोक्ता व्याख्याकार के लिए


99

जावा सीखने वाले एक गैर-जावा प्रोग्रामर के रूप में, मैं इस समय के बारे में Supplierऔर Consumerइंटरफेस पढ़ रहा हूं । और मैं उनके उपयोग और अर्थ के आसपास अपना सिर नहीं लपेट सकता। आप इन इंटरफेस का उपयोग कब और क्यों करेंगे? क्या कोई मुझे इसका सरल उदाहरण दे सकता है ... मुझे लगता है कि डॉक्टर उदाहरण मेरी समझ के लिए पर्याप्त नहीं हैं।


4
एपीआई डॉक्टर के प्रत्येक पृष्ठ के लिए एक कड़ी शीर्ष पर "उपयोग" आप के लिए क्लिक कर सकते हैं जो लेबल है Consumerऔर Supplierतुम भी खोज कर सकते हैं ट्यूटोरियल के लिए Consumer...
होल्गर

7
मुझे स्टुअर्ट मार्क्स द्वारा जवाब पसंद है। और मुझे लगता है कि नीचे उत्तर देने वाले अधिकांश लोग बिंदु से चूक गए। प्रश्न आपूर्तिकर्ता, उपभोक्ता और कार्य लिखने के लिए "कैसे" नहीं है। यह "क्यों" दुनिया में आप करना चाहते हैं? एक व्यक्ति जो उनके लिए उपयोग नहीं किया जाता है, वे कोड को बहुत अधिक जटिल बनाते हैं। लेकिन इनका उपयोग करने का लाभ स्पष्ट नहीं है।
anton1980

जहां तक ​​मैं देख सकता हूं (और मैं आपकी निराशा को मूर्त विवरण के साथ साझा करता हूं) यह कोड के एक टुकड़े में उपयोग की गई वस्तु से वस्तु-प्रकार और वस्तु-उपचार दोनों को अलग करने का एक चालाक तरीका है। यह एक ही कोड को कई अलग-अलग प्रकार के ऑब्जेक्ट को अलग-अलग नई कक्षाओं को परिभाषित करके और उन्हें आपूर्तिकर्ता और उपभोक्ता इंटरफेस में इंजेक्ट करके अनुमति देता है। इसलिए, एक पुलिस रिकॉर्ड प्रणाली में, एक ही सतही कोड का उपयोग सभी संदिग्धों के लिए किया जाता है, लेकिन प्रत्येक के लिए अंतिम प्रिंटआउट प्रत्येक संदिग्ध के वर्गीकरण पर निर्भर करता है, जैसे 'नागरिक', 'क्षुद्र', 'लार्सन', 'फेलन', 'कठोर', आदि
ट्रंक

जवाबों:


95

यह आपूर्तिकर्ता है:

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

3
तो, एक आपूर्तिकर्ता एक विधि का एक उदाहरण बनाने का एक तरीका है जो 'कुछ' लौटाता है?
जेम्स इमान

3
@jamesemanon बिल्कुल। यह एक विधि संदर्भ या लंबोदर हो सकता है।
रोहित जैन

14
सीधे तरीके से फोन करने के बजाय इसका क्या फायदा है? क्या यह इसलिए है क्योंकि आपूर्तिकर्ता एक मध्यस्थ की तरह काम कर सकता है और उस "रिटर्न" मूल्य को बंद कर सकता है?
जेम्स इमान

1
उपभोक्ता <Integer, Integer> मान्य नहीं है। एक उपभोक्ता के पास एक ही प्रकार का पैरामीटर होता है।
नासकार

2
लेकिन ऐसा निर्माण क्यों करें? जावा में होने से क्या समस्या हल होती है?
ट्रंक

175

इसका कारण यह है कि कार्यात्मक इंटरफेस के अर्थ को समझने में आपको कठिनाई हो रही है, जैसे java.util.functionकि यहाँ परिभाषित इंटरफेस का कोई अर्थ नहीं है! वे मुख्य रूप से संरचना का प्रतिनिधित्व करने के लिए मौजूद हैं , न कि शब्दार्थ

यह अधिकांश जावा एपीआई के लिए atypical है। विशिष्ट जावा एपीआई, जैसे कि एक वर्ग या इंटरफ़ेस, का अर्थ है, और आप इसके लिए संचालन को समझने के लिए एक मानसिक मॉडल विकसित कर सकते हैं जो इसका प्रतिनिधित्व करता है और इसका उपयोग करता है। 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>एपीआई में, निम्नलिखित है:

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

(संक्षिप्तता के लिए वाइल्डकार्ड्स)

आह, यह उपयोग Function"मैपिंग फ़ंक्शन" के रूप में है। वह क्या करता है? इस संदर्भ में, यदि keyमानचित्र में पहले से मौजूद नहीं है, तो मैपिंग फ़ंक्शन को कहा जाता है और इसे कुंजी सौंप दिया जाता है और मान उत्पन्न करने की अपेक्षा की जाती है, और परिणामस्वरूप कुंजी-मूल्य जोड़ी को मानचित्र में डाला जाता है।

इसलिए आप Function(या उस मामले के लिए किसी भी अन्य कार्यात्मक इंटरफेस) के विनिर्देश को नहीं देख सकते हैं और वे जो भी चाहते हैं उसे समझने का प्रयास करेंगे। आपको यह देखना होगा कि वे अन्य APIs में कहाँ उपयोग किए जाते हैं, यह समझने के लिए कि उनका क्या मतलब है, और यह अर्थ केवल उस संदर्भ पर लागू होता है।


3
तो मूल रूप से, यह केवल प्रकार के रूप में कार्य करता है
JGuo

एक और उपयोगी जानकारी हो सकती है कि कार्यात्मक इंटरफेस में कई कार्यान्वित विधियां हो सकती हैं जो आपके कोड में व्यवहार जोड़ सकती हैं
झोन मारियो लोटेरो

28

A Supplierऐसी विधि है जो कोई तर्क नहीं लेती है और एक मूल्य लौटाती है। इसका काम वस्तुतः एक अपेक्षित वर्ग के उदाहरण की आपूर्ति करना है। उदाहरण के लिए, 'गेट्टर' पद्धति का प्रत्येक संदर्भ एक हैSupplier

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

इसका उदाहरण विधि संदर्भ myClass::getCountका एक उदाहरण है Supplier<Integer>

A Consumerऐसी कोई भी विधि है जो तर्क लेती है और कुछ नहीं लौटाती है। इसके दुष्प्रभावों के लिए इसे आमंत्रित किया जाता है। जावा शब्दों में, Consumerएक voidविधि के लिए एक मुहावरा है । 'सेटर' विधियाँ एक अच्छा उदाहरण हैं:

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

इसका उदाहरण विधि संदर्भ myClass::setCountका एक उदाहरण है Consumer<Integer>और IntConsumer

A Function<A,B>ऐसी कोई भी विधि है जो एक प्रकार का तर्क लेती है, और दूसरे को लौटाती है। इसे 'परिवर्तन' के रूप में जाना जा सकता है। एक Function<A,B>लेता है Aऔर एक रिटर्न देता है B। उल्लेखनीय यह है कि दिए गए मान के लिए A, फ़ंक्शन को हमेशा एक विशिष्ट मान वापस करना चाहिए BAऔर Bवास्तव में एक ही प्रकार हो सकता है, जैसे कि निम्नलिखित:

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

इसका उदाहरण विधि संदर्भ myClass:addTwoFunction<Integer, Integer>और ए है ToIntFunction<Integer>

एक गेट्टर के लिए क्लास विधि का संदर्भ फ़ंक्शन का एक और उदाहरण है।

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

अपने वर्ग विधि संदर्भ MyClass::getCountका एक उदाहरण है Function<MyClass,Integer>और ToIntFunction<MyClass>


15

क्यों java.util.function पैकेज में उपभोक्ता / आपूर्तिकर्ता / अन्य कार्यात्मक इंटरफेस परिभाषित किए गए हैं : उपभोक्ता और आपूर्तिकर्ता दो जावा में प्रदान किए गए इन-बिल्ट फ़ंक्शनल इंटरफेस में से दो हैं। इन सभी में निर्मित कार्यात्मक इंटरफेस का उद्देश्य है सामान्य फ़ंक्शन डिस्क्रिप्टर (कार्यात्मक विधि हस्ताक्षर / परिभाषा) वाले कार्यात्मक इंटरफ़ेस के लिए एक तैयार "टेम्पलेट" प्रदान करने के लिए।

Lets का कहना है कि हमें एक टाइप T को दूसरे प्रकार R में बदलने की आवश्यकता है। यदि हम किसी भी फ़ंक्शन को एक पैरामीटर के रूप में इस तरह से परिभाषित करते हैं, तो उस पद्धति को एक कार्यात्मक इंटरफ़ेस को परिभाषित करने की आवश्यकता होगी जिसका कार्यात्मक / सार विधि पैरामीटर लेती है टाइप टी इनपुट के रूप में और आउटपुट के रूप में टाइप आर का एक पैरामीटर देता है। अब, इस तरह के कई परिदृश्य हो सकते हैं और प्रोग्रामर अपनी जरूरतों के लिए कई कार्यात्मक इंटरफेस को परिभाषित करेंगे। इस तरह के परिदृश्य से बचने के लिए, प्रोग्रामिंग को आसान बनाने और कार्यात्मक इंटरफेस के उपयोग में एक सामान्य मानक लाने के लिए, इन-पेड, फंक्शन, उपभोक्ता और आपूर्तिकर्ता जैसे कार्यात्मक कार्यात्मक इंटरफेस का एक सेट परिभाषित किया गया है।

उपभोक्ता क्या करता है : उपभोक्ता कार्यात्मक इंटरफ़ेस एक इनपुट स्वीकार करता है, उस इनपुट के साथ कुछ करता है और कोई आउटपुट नहीं देता है। इसकी परिभाषा इस प्रकार है (जावा स्रोत से) -

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

यहां स्वीकार () कार्यात्मक \ सार विधि है जो इनपुट लेती है और कोई आउटपुट नहीं देती है। इसलिए, यदि आप एक इंटेगर इनपुट करना चाहते हैं, तो इसके साथ कुछ करें, जिसमें कोई आउटपुट नहीं है, फिर अपने स्वयं के इंटरफ़ेस को परिभाषित करने के बजाय उपभोक्ता के एक उदाहरण का उपयोग करें।

आपूर्तिकर्ता क्या करता है : आपूर्तिकर्ता कार्यात्मक इंटरफ़ेस कोई इनपुट नहीं लेता है, लेकिन आउटपुट देता है। इसकी परिभाषा इस प्रकार है (जावा स्रोत से) -

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

जहां आपको एक फ़ंक्शन की आवश्यकता होती है, जो कुछ लौटाता है, एक इंटेगर कहते हैं, लेकिन कोई आउटपुट नहीं लेता है जो आपूर्तिकर्ता का एक उदाहरण है।

यदि उपभोक्ता और आपूर्तिकर्ता इंटरफेस के उदाहरण उपयोग के साथ-साथ अधिक स्पष्टता की आवश्यकता होती है, तो आप मेरे ब्लॉग पोस्टों को उसी पर संदर्भित कर सकते हैं - 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/


12

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

0

आम लोगों की शर्तों में,

आपूर्तिकर्ता डेटा की आपूर्ति करेगा लेकिन किसी भी डेटा का उपभोग किए बिना। प्रोग्रामिंग के संदर्भ में एक विधि जो किसी भी तर्क को नहीं लेती है, लेकिन एक मान लौटाती है। इसका उपयोग नए मान उत्पन्न करने के लिए किया जाता है।

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

उपभोक्ता डेटा का उपभोग करेगा लेकिन कोई डेटा वापस नहीं करेगा। प्रोग्रामिंग के संदर्भ में एक विधि जो कई तर्क लेती है और किसी भी मूल्य को वापस नहीं करती है।

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


0

उपभोक्ता और आपूर्तिकर्ता जावा द्वारा प्रदान किए गए इंटरफेस हैं। उपभोक्ता सूची तत्वों पर पुनरावृति के लिए उपयोग करता है और आपूर्तिकर्ता आपूर्ति वस्तु के लिए उपयोग होता है

आप कोड प्रदर्शन के साथ आसानी से समझ सकते हैं।

उपभोक्ता

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

}

0

सबसे सरल उत्तर हो सकता है:

एक उपभोक्ता को फंक्शन <T, Void> के रूप में देखा जा सकता है। एक सप्लायर को फंक्शन <शून्य, टी> के रूप में देखा जा सकता है।


0

संक्षेप में,

  1. प्रदायक

एक अनाम फ़ंक्शन का प्रतिनिधित्व करता है जो बिना किसी तर्क के स्वीकार करता है और परिणाम उत्पन्न करता है।

  1. उपभोक्ता

एक अनाम फ़ंक्शन का प्रतिनिधित्व करता है जो एक तर्क को स्वीकार करता है और कोई परिणाम नहीं देता है।

इसके अलावा, एक विधेय है । प्रेडिकेट एक अनाम फ़ंक्शन का प्रतिनिधित्व करता है जो एक तर्क को स्वीकार करता है और एक परिणाम पैदा करता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.