জাভাতে ptionচ্ছিক বা ইলেস ptionচ্ছিক


137

আমি জাভা 8- এ নতুন ptionচ্ছিক প্রকারের সাথে কাজ করছি , এবং আমি এমন একটি সাধারণ অপারেশন বলে মনে করি যা কার্যত সমর্থিত নয়: একটি "orElseOptional"

নিম্নলিখিত নিদর্শন বিবেচনা করুন:

Optional<Result> resultFromServiceA = serviceA(args);
if (resultFromServiceA.isPresent) return result;
else {
    Optional<Result> resultFromServiceB = serviceB(args);
    if (resultFromServiceB.isPresent) return resultFromServiceB;
    else return serviceC(args);
}

এই প্যাটার্নের অনেকগুলি রূপ রয়েছে তবে এটি একটি onচ্ছিক "orElse" চাওয়াতে উত্সাহিত করে যা একটি নতুন alচ্ছিক উত্পাদন করার জন্য একটি ফাংশন নেয়, কেবলমাত্র বর্তমানের অস্তিত্ব না থাকলে তাকে ডাকা হয়।

এটির বাস্তবায়নটি এর মতো দেখায়:

public Optional<T> orElse(Supplier<Optional<? extends T>> otherSupplier) {
    return value != null ? this : other.get();
}

আমি কৌতূহলবোধ করি যদি এমন কোনও পদ্ধতির অস্তিত্ব না থাকে, যদি আমি কেবল অপ্রয়োজনীয় উপায়ে ptionচ্ছিকভাবে ব্যবহার করি এবং লোকেরা কীভাবে অন্যান্য ক্ষেত্রে এই মামলাটি মোকাবেলা করতে এসেছে।

আমার বলা উচিত যে আমি মনে করি যে কাস্টম ইউটিলিটি ক্লাস / পদ্ধতিগুলির সাথে জড়িত সমাধানগুলি মার্জিত নয় কারণ আমার কোড নিয়ে কাজ করা লোকেরা অগত্যা তাদের অস্তিত্ব বুঝতে পারে না।

এছাড়াও, যদি কেউ জানে, এই জাতীয় পদ্ধতিটি জেডিকে 9-তে অন্তর্ভুক্ত করা হবে এবং আমি কোথায় এই জাতীয় পদ্ধতির প্রস্তাব দিতে পারি? এটি আমার কাছে এপিআই-তে একটি চমকপ্রদ বাদ দেওয়ার মতো বলে মনে হচ্ছে।


13
এই সমস্যাটি দেখুন । স্পষ্ট করার জন্য: এটি ইতিমধ্যে জাভা 9-এ হতে চলেছে - জাভা 8 এর ভবিষ্যতের আপডেটে না হলে
ওবিসের

এইটা! ধন্যবাদ, আমার অনুসন্ধানে এটি খুঁজে পেল না।
ইয়োনা অ্যাপলেট্রি

2
@ ওবিসিরে এই সমস্যাটি এখানে প্রয়োগ হয় না কারণ এটি খালি ptionচ্ছিক আচরণ সম্পর্কিত , বিকল্প ফলাফল সম্পর্কে নয় । orElseGet()OP চ্ছিক ইতিমধ্যে ওপি-র প্রয়োজনের জন্য রয়েছে, কেবল এটি দুর্দান্ত ক্যাসকেডিং সিনট্যাক্স তৈরি করে না।
মার্কো টপলনিক


উত্তর:


86

এটি রূপে জেডিকে 9 এর অংশ or, যা গ্রহণ করে Supplier<Optional<T>>। আপনার উদাহরণটি তখন হবে:

return serviceA(args)
    .or(() -> serviceB(args))
    .or(() -> serviceC(args));

বিশদগুলির জন্য জাভাদোক বা এই পোস্টটি আমি লিখেছি।


খুশী হলাম। এই সংযোজনটি অবশ্যই এক বছরের পুরানো হতে পারে এবং আমি লক্ষ্য করি না। আপনার ব্লগে প্রশ্নটি সম্পর্কে, রিটার্নের ধরণটি পরিবর্তন করা বাইনারি সামঞ্জস্যতাটিকে ভেঙে দেবে, কারণ বাইটকোড আহ্বান নির্দেশাবলী রিটার্নের প্রকার সহ পুরো স্বাক্ষরকে নির্দেশ করে, সুতরাং রিটার্নের ধরণের পরিবর্তন করার কোনও সুযোগ নেই ifPresent। তবে যাইহোক, আমার মনে হয় নামটি ifPresentযাইহোক ভাল হয় না। নামে অন্য সব পদ্ধতি না জন্মদান "অন্য" (যেমন map, filter, flatMap), এটা উহ্য হয় যে, তারা কিছুই করতে যদি কোনো মূল্যই বর্তমান, তাই কেন ifPresent...
হোলগার

সুতরাং Optional<T> perform(Consumer<T> c)শৃঙ্খলার অনুমতি দেওয়ার জন্য একটি পদ্ধতি যুক্ত করা perform(x).orElseDo(y)( orElseDoআপনার প্রস্তাবিত বিকল্প হিসাবে ifEmpty, elseঅনুপস্থিত মানগুলির জন্য কিছু করতে পারে এমন সমস্ত পদ্ধতির নামে সামঞ্জস্যপূর্ণ )। আপনি performজাভা 9 তে stream().peek(x).findFirst()এটি এপিআই-র অপব্যবহারের মাধ্যমে নকল করতে পারেন এবং একই সাথে Runnableএকটি নির্দিষ্টকরণ ব্যতীত কার্যকর করার কোনও উপায় এখনও নেই Consumer
হলগার

65

বর্তমান এপিআই দেওয়া সবচেয়ে পরিষ্কার "চেষ্টা পরিষেবা" পদ্ধতির হ'ল:

Optional<Result> o = Stream.<Supplier<Optional<Result>>>of(
    ()->serviceA(args), 
    ()->serviceB(args), 
    ()->serviceC(args), 
    ()->serviceD(args))
.map(Supplier::get)
.filter(Optional::isPresent)
.map(Optional::get)
.findFirst();

গুরুত্বপূর্ণ দিকটি আপনাকে একবার লিখতে হবে অপারেশনগুলির (ধ্রুবক) চেইন নয় তবে অন্য কোনও পরিষেবা যুক্ত করা (বা পরিষেবাদির তালিকাটি সাধারণভাবে সংশোধন করা সাধারণ) কতটা সহজ। এখানে, একক যোগ বা অপসারণ ()->serviceX(args)যথেষ্ট is

স্ট্রিমগুলির অলস মূল্যায়নের কারণে, পূর্ববর্তী কোনও পরিষেবা যদি শূন্যস্থান না দেয় তবে কোনও পরিষেবা চাওয়া হবে না Optional


13
একটি প্রকল্পে সবেমাত্র এটি ব্যবহৃত হয়েছে, godশ্বরকে ধন্যবাদ আমরা যদিও কোড রিভিউ করি না।
ইলিয়া স্মাগিন

3
"OrElseGet" এর চেইনের চেয়ে এটি অনেক বেশি পরিষ্কার, তবে এটি পড়াও বেশ শক্ত।
স্লারতিদান

4
এটি অবশ্যই সঠিক ... তবে সত্যি কথা বলতে, এটি বিশ্লেষণ করতে আমার এক সেকেন্ড সময় লাগে এবং আমি সত্য বলে আত্মবিশ্বাস নিয়ে ফিরে যাই না। মনে মনে, আমি বুঝতে পারি যে এই উদাহরণটি, তবে আমি একটি ছোট্ট পরিবর্তনটি কল্পনা করতে পারি যা এটি অলসভাবে মূল্যায়ন না করা বা অন্য কোনও ত্রুটি রয়েছে যা এক নজরে পৃথক হতে পারে। আমার কাছে, এটি হ'ল-শালীন-হিসাবে-একটি-ইউটিলিটি-ফাংশন বিভাগে।
ইওনা অ্যাপলেট্রি

3
আমি ভাবছি যদি সুইচিং .map(Optional::get)সঙ্গে .findFirst(), "পড়তে" সহজে করতে হবে যেমন .filter(Optional::isPresent).findFirst().map(Optional::get)হতে পারে মত "স্ট্রীম, যার জন্য ঐচ্ছিক :: isPresent সত্য প্রথম উপাদান খুঁজে পেতে এবং তারপর আবেদন ঐচ্ছিক :: পেতে দ্বারা এটি চেপ্টা" "পড়া"?
স্কেচেন ten

3
মজার, আমি কয়েক মাস আগে একটি অনুরূপ প্রশ্নের জন্য খুব অনুরূপ সমাধান পোস্ট করেছি । এই প্রথম আমি এই জুড়ে আসছে।
shmosel

34

এটি সুন্দর নয়, তবে এটি কাজ করবে:

return serviceA(args)
  .map(Optional::of).orElseGet(() -> serviceB(args))
  .map(Optional::of).orElseGet(() -> serviceC(args))
  .map(Optional::of).orElseGet(() -> serviceD(args));

.map(func).orElseGet(sup)এর সাথে ব্যবহারের জন্য মোটামুটি সহজ প্যাটার্ন Optional। এর অর্থ "যদি Optionalএর মান থাকে তবে vআমাকে দিন func(v), অন্যথায় আমাকে দিন sup.get()"।

এই ক্ষেত্রে, আমরা কল serviceA(args)এবং একটি পেতে Optional<Result>। যদি Optionalএর মান থাকে তবে vআমরা পেতে চাই Optional.of(v), তবে এটি খালি থাকলে আমরা পেতে চাই serviceB(args)। আরও বিকল্প দিয়ে ধুয়ে - পুনরাবৃত্তি।

এই প্যাটার্নের অন্যান্য ব্যবহারগুলি

  • .map(Stream::of).orElseGet(Stream::empty)
  • .map(Collections::singleton).orElseGet(Collections::emptySet)

1
হু, আমি যখন এই কৌশলটি ব্যবহার করি, তখন গ্রহনটি বলে: "বিকল্প <স্ট্রিং> প্রকারের পদ্ধতি বা ইলেসগেট (সরবরাহকারী <? স্ট্রিং> প্রসারিত) আর্গুমেন্টের জন্য প্রযোজ্য নয় (() -> {})" মনে হয় না onচ্ছিক একটি বৈধ কৌশল, স্ট্রিংয়ে ফেরত বিবেচনা করার জন্য ??
ক্রিসমার্কস

@ chrismarx () -> {}একটি ফেরত দেয় না Optional। তুমি অর্জন করার জন্য কি চেষ্টা করতেছ?
মিশা

1
আমি শুধু উদাহরণ অনুসরণ করার চেষ্টা করছি। মানচিত্রের কলগুলির শৃঙ্খলা কাজ করছে না। আমার পরিষেবাগুলি স্ট্রিংগুলি ফেরত দেয় এবং অবশ্যই তখন কোনও ম্যাপ () বিকল্প উপলব্ধ নেই
ক্রিসমার্কস

1
or(Supplier<Optional<T>>)জাভা 9 আসার জন্য দুর্দান্ত পঠনযোগ্য বিকল্প
ডেভিড এম

1
@ শিপী আপনার ভুল হয়েছে। .map()একটি খালি একটি খালি Optionalউত্পাদন করবে Optional
মিশা

27

সম্ভবত এটি আপনার পরে যাচ্ছেন: oneচ্ছিক বা অন্য কোনওটির কাছ থেকে মূল্য পান

অন্যথায়, আপনি একবার দেখতে চাইবেন Optional.orElseGet। আমি মনে করি যে আপনি পরে যাচ্ছেন তার একটি উদাহরণ এখানে দেওয়া হয়েছে :

result = Optional.ofNullable(serviceA().orElseGet(
                                 () -> serviceB().orElseGet(
                                     () -> serviceC().orElse(null))));

2
প্রতিভা সাধারণত এটিই করে। Ulচ্ছিকটিকে একটি শোধনযোগ্য হিসাবে মূল্যায়ন করুন এবং এটিকে মুড়িয়ে ফেলা ofNullableহ'ল এটি আমার দেখা শীতলতম জিনিস।
জিন কোওন

5

ধরে নিই যে আপনি এখনও জেডিকে 8 এ রয়েছেন, বেশ কয়েকটি বিকল্প রয়েছে।

বিকল্প # 1: আপনার নিজের সহায়ক পদ্ধতি তৈরি করুন

উদাহরণ:

public class Optionals {
    static <T> Optional<T> or(Supplier<Optional<T>>... optionals) {
        return Arrays.stream(optionals)
                .map(Supplier::get)
                .filter(Optional::isPresent)
                .findFirst()
                .orElseGet(Optional::empty);
    }
}

যাতে আপনি করতে পারেন:

return Optionals.or(
   ()-> serviceA(args),
   ()-> serviceB(args),
   ()-> serviceC(args),
   ()-> serviceD(args)
);

বিকল্প # 2: একটি লাইব্রেরি ব্যবহার করুন

যেমন গুগল পেয়ারার or()ptionচ্ছিক একটি যথাযথ অপারেশনকে সমর্থন করে (ঠিক জেডিকে 9 এর মতো), যেমন:

return serviceA(args)
  .or(() -> serviceB(args))
  .or(() -> serviceC(args))
  .or(() -> serviceD(args));

(যেখানে প্রতিটি পরিষেবা com.google.common.base.Optionalপরিবর্তে ফিরে আসে java.util.Optional)।


আমি Optional<T>.or(Supplier<Optional<T>>)পেয়ারা ডক্সে পাইনি । আপনি যে জন্য একটি লিঙ্ক আছে না?
তামাস হেজেডাস

.orElseGet টি টি দেয় কিন্তু alচ্ছিক :: খালি রিটার্ন Oচ্ছিক <টি>। @Ioobe দ্বারা বর্ণিত হিসাবে bleচ্ছিক.ওফনযোগ্য (........ বা ইলসে (নাল)) এর পছন্দসই প্রভাব রয়েছে।
মিগুয়েল পেরেরা

@ টামাসেজেদুস আপনি # 1 বিকল্পের মানে? এটি একটি কাস্টম বাস্তবায়ন যা এর উপরে ছিটানো রয়েছে। PS: দেরী জবাবের জন্য দুঃখিত
শিপি

@ মিগুয়েলপিয়েরা .অরএলসগেট এই ক্ষেত্রে returnsচ্ছিক <টি> ফেরত দেয় কারণ এটি ptionচ্ছিক <অপশনাল <টি>>
শিপি

2

এই প্যাটার্ন ম্যাচিং একটি ভাল হইয়া এবং কিছু সঙ্গে একটি অধিক প্রথাগত অপশন ইন্টারফেস এবং কোনটি বাস্তবায়নের (যেমন ঐ মতো দেখায় Javaslang , FunctionalJava ) অথবা একটি অলস হতে পারে মধ্যে বাস্তবায়ন সাইক্লপ্স-প্রতিক্রিয়া .I'm এই লাইব্রেরি লেখক।

সঙ্গে সাইক্লপ্স-প্রতিক্রিয়া আপনার কাছে কাঠামোগত ব্যবহার করতে পারেন প্যাটার্ন ম্যাচিং JDK ধরনের। Ptionচ্ছিকর জন্য আপনি বর্তমান এবং অনুপস্থিত ক্ষেত্রে দর্শনার্থীর প্যাটার্নের মাধ্যমে মিল করতে পারেন । এটি দেখতে এরকম কিছু লাগবে -

  import static com.aol.cyclops.Matchables.optional;

  optional(serviceA(args)).visit(some -> some , 
                                 () -> optional(serviceB(args)).visit(some -> some,
                                                                      () -> serviceC(args)));
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.