আমি কীভাবে নতুন কম্পিউটআইফএবসেন্ট ফাংশনটি ব্যবহার করব?


115

আমি ম্যাপ ডটকমপিটআইএফএবসেন্টটি ব্যবহার করতে চাই তবে ল্যাম্বডাস আন্ডারগ্র্যাডের থেকে অনেক দীর্ঘ হয়েছে।

ডক্স থেকে প্রায় সরাসরি: এটি কাজ করার পুরানো পদ্ধতির উদাহরণ দেয়:

Map<String, Boolean> whoLetDogsOut = new ConcurrentHashMap<>();
String key = "snoop";
if (whoLetDogsOut.get(key) == null) {
  Boolean isLetOut = tryToLetOut(key);
  if (isLetOut != null)
    map.putIfAbsent(key, isLetOut);
}

এবং নতুন উপায়:

map.computeIfAbsent(key, k -> new Value(f(k)));

তবে তাদের উদাহরণে, আমি মনে করি আমি যথেষ্ট "এটি পাচ্ছি না"। এটি প্রকাশের জন্য নতুন ল্যাম্বদা উপায়টি ব্যবহার করার জন্য আমি কীভাবে কোডটি রূপান্তর করব?


আমি নিশ্চিত না যে আপনি সেখানে উদাহরণ থেকে বুঝতে পারছেন না?
লুই ওয়াসারম্যান

2
"কে" কি? এটি একটি পরিবর্তনশীল সংজ্ঞায়িত হচ্ছে? কীভাবে "নতুন মান" - এটি জাভা 8 এর কিছু, বা আমার কোনও সংজ্ঞায়িত বা ওভাররাইড করা প্রয়োজন এমন একটি বিষয় প্রতিনিধিত্ব করছে? whoLetDogsOut.computeIfAbmitted (কী, কে -> নতুন বুলিয়ান (ট্রাইটলিটআউট (কে))) সংকলন করে না, তাই আমি কিছু মিস করছি ...
বেনজামিন এইচ

ঠিক কি সংকলন না? এটি কোন ত্রুটি সৃষ্টি করে?
axtavt

টেম্প.জভা 26: ত্রুটি: অবৈধভাবে এক্সপ্রেশনটি শুরু করুন whoLetDogsOut.computeIfAbmitted (কী, কে -> নতুন বুলিয়ান (ট্রাইটলেটলেট (কে))); (">" এর দিকে ইঙ্গিত করে)
বেনজামিন এইচ

আমার জন্য জরিমানা সংকলন। আপনি সত্যই জাভা 8 সংকলক ব্যবহার করেছেন তা নিশ্চিত করুন। অন্যান্য জাভা 8 বৈশিষ্ট্যগুলি কি কাজ করে?
axtavt

উত্তর:


97

ধরুন আপনার নিম্নলিখিত কোড রয়েছে:

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class Test {
    public static void main(String[] s) {
        Map<String, Boolean> whoLetDogsOut = new ConcurrentHashMap<>();
        whoLetDogsOut.computeIfAbsent("snoop", k -> f(k));
        whoLetDogsOut.computeIfAbsent("snoop", k -> f(k));
    }
    static boolean f(String s) {
        System.out.println("creating a value for \""+s+'"');
        return s.isEmpty();
    }
}

তারপরে আপনি বার্তাটি দেখতে পাবেন creating a value for "snoop"ঠিক দ্বিতীয় বারের মতো, computeIfAbsentইতিমধ্যে সেই কীটির জন্য একটি মান রয়েছে। kল্যামডা এক্সপ্রেশনেk -> f(k) মাত্র কী ব্যবহার করুন যা মানচিত্রের মান কম্পিউটিং জন্য আপনার ল্যামডা পাস জন্য একটি placeolder (প্যারামিটার) হয়। সুতরাং উদাহরণে কীটি ফাংশন অনুরোধে পাস করা হয়েছে।

বিকল্পভাবে আপনি লিখতে পারেন: whoLetDogsOut.computeIfAbsent("snoop", k -> k.isEmpty());সাহায্যকারী পদ্ধতি ছাড়াই একই ফলাফল অর্জন করতে (তবে আপনি তখন ডিবাগিং আউটপুট দেখতে পাবেন না)। এমনকি সহজ, এটি কোনও বিদ্যমান পদ্ধতির একটি সহজ প্রতিনিধি যা আপনি লিখতে পারেন:whoLetDogsOut.computeIfAbsent("snoop", String::isEmpty); এই প্রতিনিধিদলের কোনও পরামিতি লেখার প্রয়োজন নেই।

আপনার প্রশ্নের উদাহরণ কাছাকাছি হতে, আপনি এটা লিখতে পারে যেমন whoLetDogsOut.computeIfAbsent("snoop", key -> tryToLetOut(key));(এটা কোন ব্যাপার না কিনা প্যারামিটার নাম kবা key)। অথবা এটা লিখতে যেমন whoLetDogsOut.computeIfAbsent("snoop", MyClass::tryToLetOut);যদি tryToLetOutহয় staticবা whoLetDogsOut.computeIfAbsent("snoop", this::tryToLetOut);যদি tryToLetOutএকটি দৃষ্টান্ত পদ্ধতি।


114

সম্প্রতি আমিও এই পদ্ধতিটি নিয়ে খেলছিলাম। ফিবোনাকির সংখ্যা ক্যালকুয়েলে একটি স্মৃতিযুক্ত অ্যালগরিদম লিখেছিলাম যা পদ্ধতিটি কীভাবে ব্যবহার করতে হয় সে সম্পর্কে অন্য চিত্র হিসাবে কাজ করতে পারে।

আমরা মানচিত্রটি সংজ্ঞায়িত করে এবং এর মধ্যে বেস কেসগুলির জন্য মানগুলি রেখে, fibonnaci(0)এবং fibonacci(1):

private static Map<Integer,Long> memo = new HashMap<>();
static {
   memo.put(0,0L); //fibonacci(0)
   memo.put(1,1L); //fibonacci(1)
}

এবং প্ররোচিত পদক্ষেপের জন্য আমাদের যা করতে হবে তা হ'ল আমাদের ফিবোনাচি ফাংশনটিকে নিম্নরূপে সংজ্ঞায়িত করতে হবে:

public static long fibonacci(int x) {
   return memo.computeIfAbsent(x, n -> fibonacci(n-2) + fibonacci(n-1));
}

আপনি দেখতে পাচ্ছেন যে পদ্ধতিটি computeIfAbsentমানচিত্রে উপস্থিত না থাকলে ফিবোনাচি নম্বর গণনা করতে প্রদত্ত ল্যাম্বডা এক্সপ্রেশনটি ব্যবহার করবে। এটি ট্র্যাডিশনাল, ট্রি রিরসিভ অ্যালগরিদমের তুলনায় উল্লেখযোগ্য উন্নতির প্রতিনিধিত্ব করে।


18
ডায়নামিক প্রোগ্রামিংয়ে দুর্দান্ত, একক-লাইন রূপান্তর। খুব চতুর।
বেনিয়ামিন এইচ

3
আপনি যদি প্রথমে (এন-2) কলটি পেয়ে থাকেন তবে আপনি কম সংখ্যক পুনরাবৃত্ত কল পেতে পারেন?
থরবজর্ন রাভন অ্যান্ডারসন

9
আপনি যখন পুনরাবৃত্তি হিসাবে কম্পিউটআইএফএবসেন্ট ব্যবহার করেন তখন আপনার আরও সতর্ক হওয়া উচিত। আরও তথ্যের জন্য দয়া করে চেক করুন stackoverflow.com/questions/28840047/…
অজিত কুমার

11
এই কোড ফলাফল HashMapএর অভ্যন্তরীণ শুধু হিসাবে, দূষিত হচ্ছে bugs.openjdk.java.net/browse/JDK-8172951 এবং ব্যর্থ হয়ে যাবে ConcurrentModificationExceptionজাভা 9 (মধ্যে bugs.openjdk.java.net/browse/JDK-8071667 )
পাযত্র Findeisen

22
দস্তাবেজগুলি আক্ষরিকভাবে বলে যে ম্যাপিং ফাংশনটি গণনার সময় এই মানচিত্রটি পরিবর্তন করা উচিত নয় , সুতরাং এই উত্তরটি স্পষ্টতই ভুল।
fps

41

আরেকটি উদাহরণ. জটিল মানচিত্রের মানচিত্র তৈরি করার সময়, কম্পিউটএফএবসেন্ট () পদ্ধতিটি মানচিত্রের get () পদ্ধতির প্রতিস্থাপন। একসাথে কম্পিউটআইএফএবসেন্ট () কলগুলির শৃঙ্খলার মাধ্যমে, নিখোঁজ পাত্রে সরবরাহ করা ল্যাম্বদা এক্সপ্রেশনগুলির সাহায্যে অন-ফ্লাই তৈরি করা হয়:

  // Stores regional movie ratings
  Map<String, Map<Integer, Set<String>>> regionalMovieRatings = new TreeMap<>();

  // This will throw NullPointerException!
  regionalMovieRatings.get("New York").get(5).add("Boyhood");

  // This will work
  regionalMovieRatings
    .computeIfAbsent("New York", region -> new TreeMap<>())
    .computeIfAbsent(5, rating -> new TreeSet<>())
    .add("Boyhood");

31

বহু-মানচিত্র

এটি যদি আপনি গুগল পেয়ারা লাইব্রেরিটির প্রয়োগের জন্য অবলম্বন না করে কোনও মাল্টিম্যাপ তৈরি করতে চান তবে এটি সত্যিই সহায়কMultiMap

উদাহরণস্বরূপ, ধরুন আপনি নির্দিষ্ট শিক্ষার্থীর জন্য নিবন্ধিত শিক্ষার্থীদের একটি তালিকা সঞ্চয় করতে চান।

জেডি কে লাইব্রেরি ব্যবহার করার জন্য এর সাধারণ সমাধানটি হ'ল:

Map<String,List<String>> studentListSubjectWise = new TreeMap<>();
List<String>lis = studentListSubjectWise.get("a");
if(lis == null) {
    lis = new ArrayList<>();
}
lis.add("John");

//continue....

যেহেতু এটিতে কিছু বয়লারপ্লেট কোড রয়েছে, তাই লোকেরা পেয়ারা ব্যবহার করার প্রবণতা রাখে Mutltimap

Map.computeIfAbsent ব্যবহার করে, আমরা নীচে পেয়ারা মাল্টিম্যাপ ছাড়াই একটি লাইনে লিখতে পারি।

studentListSubjectWise.computeIfAbsent("a", (x -> new ArrayList<>())).add("John");

স্টুয়ার্ট মার্কস এবং ব্রায়ান গোয়েটস এই https://www.youtube.com/watch?v=9uTVXxJjuco সম্পর্কে ভাল কথা বলেছেন


জাভা 8 (এবং আরও সংক্ষিপ্ত) তে একটি মাল্টিম্যাপ তৈরি করার আরেকটি উপায় হ'ল এটি করা জেডিকে আরও সংক্ষিপ্তভাবে ইমোতে studentListSubjectWise.stream().collect(Collectors.GroupingBy(subj::getSubjName, Collectors.toList());বহু ধরণের মানচিত্র তৈরি করে Map<T,List<T>
জম্বিগুলি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.