कंप्लीटटेबल फ़ॉइल | तत्पश्चात


119

मैं thenApply() और के बीच के अंतर के आसपास अपना सिर नहीं मिला सकता thenCompose()

तो, क्या कोई वैध उपयोग का मामला दे सकता है?

जावा डॉक्स से:

thenApply(Function<? super T,? extends U> fn)

एक नया रिटर्न देता CompletionStageहै, जब यह चरण सामान्य रूप से पूरा होता है, इस चरण के परिणाम के साथ निष्पादित फ़ंक्शन के तर्क के रूप में निष्पादित किया जाता है।

thenCompose(Function<? super T,? extends CompletionStage<U>> fn)

एक नया रिटर्न देता CompletionStageहै, जब यह चरण सामान्य रूप से पूरा होता है, इस चरण के साथ आपूर्ति फ़ंक्शन के तर्क के रूप में निष्पादित किया जाता है।

मुझे लगता है कि 2 तर्क thenComposeपूर्ण समापन का विस्तार thenApplyकरता है जहां नहीं करता है।

क्या कोई उदाहरण दे सकता है कि मुझे किस मामले में thenApplyऔर कब उपयोग करना है thenCompose?


39
क्या आप में mapऔर के बीच का अंतर समझते हैं ? है और का है । आप होने से बचने के लिए उपयोग करते हैं । flatMapStreamthenApplymapthenComposeflatMapCompletableFuturethenComposeCompletableFuture<CompletableFuture<..>>
मिशा

2
@ मीशा आपकी टिप्पणी के लिए धन्यवाद। हाँ, मैं बीच का अंतर जानना mapऔर flatMapऔर मैं अपनी बात मिलता है। धन्यवाद फिर से :)
लड़के

जवाबों:


168

thenApply यदि आपके पास एक तुल्यकालिक मैपिंग फ़ंक्शन है, तो इसका उपयोग किया जाता है।

CompletableFuture<Integer> future = 
    CompletableFuture.supplyAsync(() -> 1)
                     .thenApply(x -> x+1);

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

CompletableFuture<Integer> future = 
    CompletableFuture.supplyAsync(() -> 1)
                     .thenCompose(x -> CompletableFuture.supplyAsync(() -> x+1));

14
के .thenCompose(x -> CompletableFuture.supplyAsync(() -> x+1))बजाय एक प्रोग्रामर का उपयोग क्यों करना चाहिए .thenApplyAsync(x -> x+1)? तुल्यकालिक या अतुल्यकालिक होने के नाते है नहीं प्रासंगिक अंतर।
होल्गर

17
वे ऐसा नहीं करेंगे। हालांकि, अगर किसी तीसरे पक्ष के पुस्तकालय का उपयोग किया जाता है CompletableFuture, तो वे वापस आ जाते हैं , तो यह वह जगह thenComposeहोगी जहां संरचना को समतल करने का तरीका होगा।
जो सी

1
@ArunavSanyal, वोट एक अलग तस्वीर दिखाते हैं। यह उत्तर स्पष्ट और संक्षिप्त है।
एलेक्स श्वेस्टरोव

@ होल्गर ने मेरा अन्य उत्तर पढ़ा यदि आप उलझन में हैं thenApplyAsyncक्योंकि यह वह नहीं है जो आप सोचते हैं कि यह है।
1283822

@ 1283822 मुझे नहीं पता कि आपको क्या लगता है कि मैं भ्रमित था और आपके उत्तर में आपके दावे के समर्थन में कुछ भी नहीं है कि "यह वह नहीं है जो आप सोचते हैं कि यह है"।
होल्गर

49

मुझे लगता है कि @ जो सी द्वारा पोस्ट किया गया उत्तर भ्रामक है।

मुझे उदाहरण के बीच thenApplyऔर उसके बीच के अंतर को समझाने की कोशिश करते हैं thenCompose

मान लीजिए कि हमारे पास 2 विधियाँ हैं: getUserInfo(int userId)और getUserRating(UserInfo userInfo):

public CompletableFuture<UserInfo> getUserInfo(userId)

public CompletableFuture<UserRating> getUserRating(UserInfo)

दोनों विधि वापसी प्रकार हैं CompletableFuture

हम getUserInfo()पहले कॉल करना चाहते हैं , और इसके पूरा होने पर, getUserRating()परिणाम के साथ कॉल करेंUserInfo

getUserInfo()विधि के पूरा होने पर , चलो दोनों का प्रयास करें thenApplyऔर thenCompose। अंतर रिटर्न प्रकारों में है:

CompletableFuture<CompletableFuture<UserRating>> f =
    userInfo.thenApply(this::getUserRating);

CompletableFuture<UserRating> relevanceFuture =
    userInfo.thenCompose(this::getUserRating);

thenCompose()स्काला कीflatMap तरह काम करता है, जो नेस्टेड वायदा को समतल करता है

thenApply()नेस्टेड फ्यूचर्स को वापस कर दिया क्योंकि वे थे, लेकिन thenCompose()नेस्टेड को चपटा कर दिया CompletableFuturesताकि इसे और अधिक कॉल करने की विधि को चेन करना आसान हो।


2
तब जो सी का जवाब भ्रामक नहीं है। यह सही और अधिक संक्षिप्त है।
'13:

2
यह बहुत मददगार था :-)
dstibbe

1
Imho यह कंप्लीटटेबल सिवनी को लिखने के लिए खराब डिज़ाइन है । उपयोग ompletableFuture.supplyAsync (x => getUserInfo (userId)) thenApply (userInfo => getUserRating (userInfo)) या इस तरह कुछ भी, यह अधिक पठनीय imho, और CompletableFuture में सभी वापसी प्रकार रैप करने के लिए अनिवार्य नहीं है
user1694306

@ user1694306 यह खराब डिज़ाइन है या नहीं, इस पर निर्भर करता है कि उपयोगकर्ता रेटिंग में निहित है UserInfo(तब हाँ) या क्या इसे अलग से प्राप्त करना है, शायद महंगा भी (तब नहीं)।
glglgl

42

जावा 9 में अपडेट किए गए Javadocs शायद इसे बेहतर समझने में मदद करेंगे:

thenApply

<U> CompletionStage<U> thenApply​(Function<? super T,? extends U> fn)

एक नया रिटर्न देता CompletionStageहै, जब यह चरण सामान्य रूप से पूरा होता है, इस चरण के परिणाम के साथ निष्पादित फ़ंक्शन के तर्क के रूप में निष्पादित किया जाता है।

इस विधि के अनुरूप है Optional.mapऔर Stream.map

CompletionStageअसाधारण पूर्णता को कवर करने वाले नियमों के लिए प्रलेखन देखें ।

thenCompose

<U> CompletionStage<U> thenCompose​(Function<? super T,? extends CompletionStage<U>> fn)

एक नया देता है जो दिए गए फ़ंक्शन द्वारा दिए गए CompletionStageमान के साथ पूरा होता है CompletionStage

जब यह चरण सामान्य रूप से पूरा हो जाता है, तो दिए गए फ़ंक्शन को इस चरण के परिणाम के साथ तर्क के रूप में लागू किया जाता है, दूसरे को लौटाता है CompletionStage। जब वह चरण सामान्य रूप से पूरा हो जाता है, तो CompletionStageइस विधि द्वारा लौटाया गया मान उसी के साथ पूरा होता है।

प्रगति सुनिश्चित करने के लिए, आपूर्ति किए गए फ़ंक्शन को अपने परिणाम के अंतिम समापन की व्यवस्था करनी चाहिए।

इस विधि के अनुरूप है Optional.flatMapऔर Stream.flatMap

CompletionStageअसाधारण पूर्णता को कवर करने वाले नियमों के लिए प्रलेखन देखें ।


14
मुझे आश्चर्य है कि उन्होंने उन कार्यों को mapऔर flatMapपहली जगह में नाम क्यों नहीं दिया ।
मथायस ब्रौन

1
@MatthiasBraun मुझे लगता है कि क्योंकि thenApply()बस फोन होगा Function.apply(), और thenCompose()रचना के कार्यों के समान है।
दिदिर एल

14

thenApplyऔर के thenComposeतरीके हैं CompletableFuture। उनका उपयोग करें जब आप करने के लिए कुछ करने के लिए करना चाहते हैं CompleteableFutureएक साथ के परिणाम Function

thenApplyऔर thenComposeदोनों CompletableFutureअपने परिणाम के रूप में लौटते हैं । आप कई thenApplyया thenComposeएक साथ चेन कर सकते हैं। Functionप्रत्येक कॉल पर आपूर्ति करें, जिसका परिणाम अगले इनपुट होगा Function

Functionआप कभी कभी आपूर्ति की कुछ तुल्यकालिक करने की जरूरत है। आपकी वापसी का प्रकार Functionगैर- Futureप्रकार होना चाहिए । इस मामले में आपको उपयोग करना चाहिए thenApply

CompletableFuture.completedFuture(1)
    .thenApply((x)->x+1) // adding one to the result synchronously, returns int
    .thenApply((y)->System.println(y)); // value of y is 1 + 1 = 2

दूसरी बार आप इसमें एसिंक्रोनस प्रोसेसिंग कर सकते हैं Function। उस स्थिति में आपको उपयोग करना चाहिए thenCompose। आपकी वापसी का प्रकार Functionए होना चाहिए CompletionStageFunctionश्रृंखला में अगला CompletionStageइनपुट के रूप में उस का परिणाम प्राप्त करेगा , इस प्रकार से अलिखित है CompletionStage

// addOneAsync may be implemented by using another thread, or calling a remote method
abstract CompletableFuture<Integer> addOneAsync(int input);

CompletableFuture.completedFuture(1)
    .thenCompose((x)->addOneAsync(x)) // doing something asynchronous, returns CompletableFuture<Integer>
    .thenApply((y)->System.println(y)); // y is an Integer, the result of CompletableFuture<Integer> above

यह जावास्क्रिप्ट के लिए एक समान विचार है PromisePromise.thenएक फ़ंक्शन को स्वीकार कर सकता है जो या तो एक मूल्य या एक मान लौटाता है Promise। जावा में इन दोनों विधियों के अलग-अलग नाम होने के कारण जेनेरिक इरेज़र हैंFunction<? super T,? extends U> fnऔर Function<? super T,? extends CompletionStage<U>> fnएक ही रनटाइम प्रकार माना जाता है - Function। इस प्रकार thenApplyऔर thenComposeसाफ़ तौर पर नामित किया जाना है, या जावा कम्पाइलर समान विधि हस्ताक्षर के बारे में शिकायत करेगा। अंतिम परिणाम, जावास्क्रिप्ट को जावा Promise.thenमें दो भागों - thenApplyऔर thenCompose- में लागू किया गया है।

आप मेरे अन्य उत्तर को पढ़ सकते हैं यदि आप संबंधित फ़ंक्शन के बारे में उलझन में हैं thenApplyAsync

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