কমপ্লিটেবল ফিউচার | তারপর অ্যাপ্লিকেশন বনাম তারপর কমপোজ


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এবং flatMapএ Stream? thenApplyহয় mapএবং thenComposeহয় flatMapএর CompletableFuture। আপনি thenComposeথাকার এড়ানোর জন্য ব্যবহার করুন CompletableFuture<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
অরুনাভসন্যাল, ভোটগুলি একটি ভিন্ন চিত্র দেখায়। এই উত্তরটি পরিষ্কার এবং সংক্ষিপ্ত।
— অ্যালেক্স শেস্তেরভ

@ হালগার আমার অন্যান্য উত্তরটি পড়ুন আপনি যদি বিভ্রান্ত হন তবে 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
তাহলে জো সি এর উত্তর বিভ্রান্তিকর নয়। এটি সঠিক এবং আরও সংক্ষিপ্ত।
— koleS

2
এটি খুব সহায়ক ছিল :-)
— ডিসটিবে

1
ইমো এটি কমপ্লেটেবলফিউচার <ইউজারআইএনফো> getUserInfo এবং কমপ্লেটেবল ফিউচার <ইউজাররেটিং> getUserRating (ইউজারআইএনফো) লিখতে খারাপ ডিজাইন \\ পরিবর্তে এটি ইউজারআইফোন getUserInfo () এবং INT getUserRating (UserInfo) হওয়া উচিত যদি আমি এটি চেইন ব্যবহার করতে চাই এবং ompletableFuture.supplyAsync (x => getUserInfo (userId)) ব্যবহার করুন। তারপরে প্রয়োগ করুন (userInfo => getUserRating (userInfo)) বা এটির মতো আরও কিছু, এটি আরও পঠনযোগ্য ইমো, এবং সমস্ত রিটার্নের
— ধরণগুলি কমপ্লেটেবলফিউচার

@ ব্যবহারকারী1694306 এটি দুর্বল ডিজাইন কিনা তা নির্ভর করে না তবে ব্যবহারকারী রেটিংটি UserInfo(তখন হ্যাঁ) অন্তর্ভুক্ত রয়েছে কিনা বা এটি আলাদাভাবে অর্জন করতে হবে কিনা, এমনকি ব্যয়বহুল (তারপরেও নয়) তার উপর নির্ভর করে ।
— glglgl

42

জাভা 9-এ আপডেট হওয়া জাভাদোকগুলি সম্ভবত এটি আরও ভালভাবে বুঝতে সহায়তা করবে:

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এই পদ্ধতিতে ফিরে আসা একই মান দিয়ে সম্পন্ন হয়।

অগ্রগতি নিশ্চিত করতে, সরবরাহিত ক্রিয়াকলাপটি অবশ্যই তার ফলাফলের শেষের ব্যবস্থা করবে completion

এই পদ্ধতি অনুরূপ Optional.flatMapএবং Stream.flatMap।

CompletionStageব্যতিক্রমী সম্পূর্ণকরণ কভার করার নিয়মগুলির জন্য ডকুমেন্টেশন দেখুন ।


14
আমি অবাক হয়েছি কেন তারা এই ফাংশনগুলির নাম রাখেনি mapএবং flatMapপ্রথম স্থানে।
— ম্যাথিয়াস ব্রাউন

1
@ মাথিয়াসব্রাউন আমার মনে হয় কারণ 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একটি হওয়া উচিত CompletionStage। Functionশৃঙ্খলে পরেরটি 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

এটি জাভাস্ক্রিপ্ট-এর অনুরূপ ধারণা Promise। Promise.thenএমন কোনও ফাংশন গ্রহণ করতে পারে যা হয় একটি মান বা একটি মানের একটি Promiseপ্রদান করে। জাভাতে এই দুটি পদ্ধতির আলাদা নাম থাকার কারণটি জেনেরিক মুছে ফেলার কারণ । Function<? super T,? extends U> fnএবং Function<? super T,? extends CompletionStage<U>> fnএকই রানটাইম টাইপ হিসাবে বিবেচিত হয় - Function। সুতরাং thenApplyএবং thenComposeআলাদাভাবে নামকরণ করতে হবে, বা জাভা সংকলক অনুরূপ পদ্ধতি স্বাক্ষর সম্পর্কে অভিযোগ করবে। জাভাস্ক্রিপ্টটি জাভা স্ক্রিপ্ট Promise.thenদুটি অংশে প্রয়োগ করা হয়েছে - thenApplyএবং thenCompose- জাভা স্ক্রিপ্ট।

আপনি যদি কোনও সম্পর্কিত ফাংশন সম্পর্কে বিভ্রান্ত হন তবে আপনি আমার অন্যান্য উত্তরটি পড়তে পারেন thenApplyAsync।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.