জাভা 8 - অপশনাল.ফ্ল্যাটম্যাপ এবং ptionচ্ছিক.ম্যাপের মধ্যে পার্থক্য


162

এই দুটি পদ্ধতির মধ্যে পার্থক্য কী: Optional.flatMap()এবং Optional.map()?

একটি উদাহরণ প্রশংসা হবে।



5
@AlexisC। আপনার লিঙ্কটি স্ট্রিমের মানচিত্র এবং ফ্ল্যাটম্যাপ সম্পর্কে ,চ্ছিক নয়।
ইরান

1
@ ইরান এতে কিছু যায় আসে না, যদি আপনি বুঝতে পারেন যে মানচিত্র / ফ্ল্যাটম্যাপ কীভাবে এটি কোনও স্ট্রিমের জন্য কিনা বা না কাজ করে তবে এটি Oচ্ছিকর ক্ষেত্রেও সমান। যদি ওপি বুঝতে পারে যে এটি স্ট্রিমের জন্য কীভাবে কাজ করে তবে তার এই প্রশ্নটি করা উচিত নয়। ধারণাটিও একই রকম।
অ্যালেক্সিস সি

2
@AlexisC। আসলে তা না. স্ট্রিমের ফ্ল্যাটম্যাপের সাথে ptionচ্ছিকের ফ্ল্যাটম্যাপের সামান্য মিল রয়েছে।
ইরান

1
@ ইরান আমি মানচিত্র এবং ফ্ল্যাটম্যাপের মধ্যে ধারণাগত পার্থক্যের কথা বলছি , আমি Stream#flatMapএবং এর মধ্যে একের সাথে একযোগে যোগাযোগ রাখছি না Optional#flatMap
অ্যালেক্সিস সি

উত্তর:


166

ব্যবহারের mapফাংশন বস্তুর আপনার যা দরকার বা ফেরৎ যদি flatMapযদি ফাংশন আয় একটি Optional। উদাহরণ স্বরূপ:

public static void main(String[] args) {
  Optional<String> s = Optional.of("input");
  System.out.println(s.map(Test::getOutput));
  System.out.println(s.flatMap(Test::getOutputOpt));
}

static String getOutput(String input) {
  return input == null ? null : "output for " + input;
}

static Optional<String> getOutputOpt(String input) {
  return input == null ? Optional.empty() : Optional.of("output for " + input);
}

উভয় মুদ্রণ বিবৃতি একই জিনিস মুদ্রণ।


5
প্রশ্ন: [flat]Mapম্যাপিং ফাংশনটি কখনও কোনও সাথে কল করবে input == null? Optionalঅনুপস্থিত থাকলে আমার বোধগম্যতা অনুসারে বাছাই করুন - [ জাভাডোক ] ( ডকস.ওরকল / জাভাসে / ৮ / ডকস / এপি / জাভা / ইউটিল/… ) এটির ব্যাক আপ মনে করছে - " যদি কোনও মান উপস্থিত থাকে তবে প্রয়োগ করুন .. । "।
বোরিস দ্য স্পাইডার

1
@ বোরিস্টস্পাইডার অপশনাল.ওফ (নাল)! =
অপশনাল.ইম্পটি

14
@DiegoMartinoia Optional.of(null)একটি হল ExceptionOptional.ofNullable(null) == Optional.empty()
বোরিস স্পাইডার

1
@ বোরিস্টস্পাইডার হ্যাঁ, আপনি ঠিক বলেছেন, আমি আপনার প্রশ্নের জবাব দেওয়ার চেষ্টা করছিলাম তবে আমি মনে করি আমি এটিকে আরও অস্পষ্ট করে তুলেছি: ধারণাগতভাবে, Optional.ofNullable (নাল) খালি হওয়া উচিত নয়, তবে বাস্তবে এটি হিসাবে বিবেচিত হয়, এবং সুতরাং মানচিত্র / ফ্ল্যাটম্যাপটি কার্যকর হয় না।
দিয়েগো মার্টিনোয়া

1
আমি মনে করি ইনপুট কখনই ফাঁকা আউটপুট বা গেটআউটপুট
ড্যানিয়েলবার্ক

55

তারা উভয় somethingচ্ছিক কিছু থেকে কোনও কিছুর জন্য একটি ফাংশন নেয়।

map()আপনার কাছে theচ্ছিকভাবে " যেমন রয়েছে " ফাংশনটি প্রয়োগ করে :

if (optional.isEmpty()) return Optional.empty();
else return Optional.of(f(optional.get()));

যদি আপনার ফাংশনটি কোনও ফাংশন থেকে থাকে তবে কী হবে T -> Optional<U>?
আপনার ফলাফল এখন একটি Optional<Optional<U>>!

এটি যা সম্পর্কিত flatMap(): যদি আপনার ফাংশনটি ইতিমধ্যে একটি প্রদান করে Optional, flatMap()কিছুটা স্মার্ট হয় এবং এটি ডাবল মোড়ানো না করে, ফিরে আসে Optional<U>

এটি দুটি কার্যকর আইডিয়মের সংমিশ্রণ: mapএবং flatten


7

দ্রষ্টব্য: - নীচে মানচিত্র এবং ফ্ল্যাটম্যাপ ফাংশনের চিত্র তুলে ধরা হয়েছে, অন্যথায় ptionচ্ছিক প্রাথমিকভাবে কেবলমাত্র রিটার্ন টাইপ হিসাবে ব্যবহার করার জন্য ডিজাইন করা হয়েছে।

আপনি ইতিমধ্যে জানেন যে ptionচ্ছিকাল এমন এক ধরণের ধারক যা একটি একক বস্তুতে থাকতে পারে বা নাও থাকতে পারে, তাই যেখানেই নাল মান আশা করে সেখানে এটি ব্যবহার করা যেতে পারে (properlyচ্ছিকভাবে সঠিকভাবে ব্যবহার করা হলে আপনি কখনই এনপিই দেখতে পাবেন না)। উদাহরণস্বরূপ, যদি আপনার এমন একটি পদ্ধতি থাকে যা প্রত্যাশা করে যে কোনও ব্যক্তির অবজেক্টটি যা অযোগ্য হতে পারে তবে আপনি পদ্ধতিটি এই জাতীয় কিছু লিখতে চাইতে পারেন:

void doSome(Optional<Person> person){
  /*and here you want to retrieve some property phone out of person
    you may write something like this:
  */
  Optional<String> phone = person.map((p)->p.getPhone());
  phone.ifPresent((ph)->dial(ph));
}
class Person{
  private String phone;
  //setter, getters
}

এখানে আপনি একটি স্ট্রিং টাইপ ফিরিয়ে দিয়েছেন যা স্বয়ংক্রিয়ভাবে একটি ptionচ্ছিক প্রকারের মধ্যে আবৃত।

ব্যক্তি শ্রেণিটি যদি এর মতো দেখায় তবে ফোনটিও ptionচ্ছিক

class Person{
  private Optional<String> phone;
  //setter,getter
}

এক্ষেত্রে চলমান মানচিত্রের ফাংশনটি theচ্ছিক ক্ষেত্রে ফিরে আসা মানটি মুড়ে দেবে এবং এর মতো কিছু দেবে:

Optional<Optional<String>> 
//And you may want Optional<String> instead, here comes flatMap

void doSome(Optional<Person> person){
  Optional<String> phone = person.flatMap((p)->p.getPhone());
  phone.ifPresent((ph)->dial(ph));
}

পুনশ্চ; আইসপ্রেস () এর মাধ্যমে এটি পরীক্ষা না করে ptionচ্ছিকটিতে কখনই গেট মেথড (যদি আপনার প্রয়োজন হয়) কল করবেন না যদি না আপনি নলপয়েন্টারএক্সেপশন ব্যতীত বাঁচতে না পারেন।


1
আমি মনে করি এই উদাহরণটি আপনার উত্তরের প্রকৃতি থেকে বিভ্রান্ত হতে পারে কারণ আপনার শ্রেণি Personঅপব্যবহার করছে Optional। এটি Optionalএই জাতীয় সদস্যদের মতো ব্যবহার করা এই আইপিএলের
অভিপ্রায়

@ 8 বিটজানকি এটি দেখানোর জন্য ধন্যবাদ, এটি স্কালার অপশন থেকে পৃথক ..
সন্দীপগোদারারা

6

যা আমাকে সাহায্য করেছিল তা হ'ল দুটি ফাংশনের উত্স কোডের দিকে নজর দেওয়া।

মানচিত্র - ফলাফলটি একটি ptionচ্ছিকভাবে মোড়ানো।

public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
    Objects.requireNonNull(mapper);
    if (!isPresent())
        return empty();
    else {
        return Optional.ofNullable(mapper.apply(value)); //<--- wraps in an optional
    }
}

ফ্ল্যাটম্যাপ - 'কাঁচা' বস্তুটি ফেরত দেয়

public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) {
    Objects.requireNonNull(mapper);
    if (!isPresent())
        return empty();
    else {
        return Objects.requireNonNull(mapper.apply(value)); //<---  returns 'raw' object
    }
}

1
flatMap"'কাঁচা' বস্তুটি ফেরত দেয়" বলতে কী বোঝ? flatMapএছাড়াও একটি ম্যাপযুক্ত বস্তু "মোড়ানো" প্রদান করে Optional। পার্থক্য হল যে ক্ষেত্রে হয় flatMap, ম্যাপার ফাংশনে ম্যাপ বস্তুর গোপন Optionalযখন mapনিজেই বস্তুর গোপন Optional
ডেরেক মাহর

@ ডেরেকমাহার আমার মুছে ফেলা হয়েছে, এটি পুনরায় পোস্ট করার দরকার নেই, কারণ আপনি নিজের মন্তব্যটি ঠিকঠাক সম্পাদনা করেছেন।
ম্যাক্সেক্সিম

3
  • Optional.map():

প্রতিটি উপাদান নেয় এবং যদি মানটি বিদ্যমান থাকে তবে এটি ফাংশনে প্রেরণ করা হয়:

Optional<T> optionalValue = ...;
Optional<Boolean> added = optionalValue.map(results::add);

এখন যোগ তিনটি মান এক রয়েছে: trueবা falseএকটি মধ্যে আবৃত ঐচ্ছিক , যদি optionalValueবর্তমান, অথবা একটি ছিল খালি ঐচ্ছিক অন্যথায়।

আপনি যদি সহজেই যে ফলাফলটি ব্যবহার করতে পারেন তবে প্রক্রিয়া করার প্রয়োজন ifPresent()না হলে এর রিটার্নের মান থাকে না:

optionalValue.ifPresent(results::add); 
  • Optional.flatMap():

একই স্ট্রিমের পদ্ধতির মতো কাজ করে। স্রোতের স্রোতে ফ্ল্যাট করে। পার্থক্য সহ যে মান উপস্থাপন করা হলে এটি ফাংশনে প্রয়োগ করা হয়। অন্যথায়, একটি খালি alচ্ছিক ফিরে আসে।

আপনি এটি alচ্ছিক মান ফাংশন কলগুলি রচনা করার জন্য ব্যবহার করতে পারেন।

ধরুন আমাদের পদ্ধতি রয়েছে:

public static Optional<Double> inverse(Double x) {
    return x == 0 ? Optional.empty() : Optional.of(1 / x);
}

public static Optional<Double> squareRoot(Double x) {
    return x < 0 ? Optional.empty() : Optional.of(Math.sqrt(x));
}

তারপরে আপনি বিপরীতে স্কোয়ার রুটটি গণনা করতে পারেন, যেমন:

Optional<Double> result = inverse(-4.0).flatMap(MyMath::squareRoot);

বা, আপনি যদি পছন্দ করেন:

Optional<Double> result = Optional.of(-4.0).flatMap(MyMath::inverse).flatMap(MyMath::squareRoot);

যদি হয় inverse()বা squareRoot()ফেরত দেয় Optional.empty()তবে ফলাফলটি খালি থাকে is


1
এটি সংকলন করে না। আপনার উভয় এক্সপ্রেশনটি আপনি যে ফলাফলটির জন্য নির্ধারিত করছেন তার দ্বিগুণের চেয়ে একটি ptionচ্ছিক <ডাবল> ফেরত দেয়।
JL_SO

@ জেএল_এস আপনি ঠিক বলেছেন কারণ বিপরীতে Optional<Double>রিটার্ন টাইপ হিসাবে টাইপ থাকে।
নাজার_আরচ

3

ঠিক আছে. আপনি যখন নেস্টেড বিকল্পগুলির মুখোমুখি হন তখন আপনাকে কেবল 'ফ্ল্যাটম্যাপ' ব্যবহার করতে হবে । উদাহরণ এখানে।

public class Person {

    private Optional<Car> optionalCar;

    public Optional<Car> getOptionalCar() {
        return optionalCar;
    }
}

public class Car {

    private Optional<Insurance> optionalInsurance;

    public Optional<Insurance> getOptionalInsurance() {
        return optionalInsurance;
    }
}

public class Insurance {

    private String name;

    public String getName() {
        return name;
    }

}

public class Test {

    // map cannot deal with nested Optionals
    public Optional<String> getCarInsuranceName(Person person) {
        return person.getOptionalCar()
                .map(Car::getOptionalInsurance) // ① leads to a Optional<Optional<Insurance>
                .map(Insurance::getName);       // ②
    }

}

স্ট্রিমের মতো, #চ্ছিক # মানচিত্র Oচ্ছিক দ্বারা মোড়ানো একটি মান প্রদান করবে। এজন্য আমরা নেস্টেড ptionচ্ছিকাল পাই - Optional<Optional<Insurance>। এবং ② এ, আমরা এটিকে একটি বীমা দৃষ্টান্ত হিসাবে মানচিত্র তৈরি করতে চাই, এইভাবেই ঘটেছিল ট্রাজেডি। মূলটি নেস্টেড অপশনাল। শেলগুলি নির্বিশেষে যদি আমরা মূল মানটি পেতে পারি তবে আমরা এটি সম্পন্ন করব। ফ্ল্যাটম্যাপ এটাই করে।

public Optional<String> getCarInsuranceName(Person person) {
    return person.getOptionalCar()
                 .flatMap(Car::getOptionalInsurance)
                 .map(Insurance::getName);
}

আপনি জাভা 8 সিস্টেমেটিকালি পড়াশোনা করতে চাইলে শেষ পর্যন্ত আমি জাভা 8 অ্যাকশন ইন অ্যাকশনটিতে দৃ stron়তার সাথে পুনঃসারণ করেছি।

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