জাভা ব্যবহার করছে ম্যাপ.কন্টেইনস কে () রিডানড্যান্ট যখন ম্যাপ.জেট ব্যবহার করে)


93

আমি কিছু সময়ের জন্য ভাবছিলাম যে containsKey()পদ্ধতিটি ব্যবহার করা থেকে বিরত থাকা java.util.Mapএবং এর পরিবর্তে ফলাফলটি বাতিল করে দেওয়া ভাল অনুশীলনের মধ্যে অনুমোদিত কি না get()

প্রথম - আমার যুক্তিপূর্ণ এটি মূল্যের লুকআপ দুইবার করতে অপ্রয়োজনীয় মনে হয় containsKey()জন্য আবার এবং তারপর get()

অন্যদিকে এটি হতে পারে যে Mapক্যাশের বেশিরভাগ মানক বাস্তবায়নগুলি শেষ দেখার জন্য বা সংকলকটি অন্যথায় অতিরিক্ত বাজেয়াপ্ত করতে পারে এবং কোডটির পাঠযোগ্যতার জন্য containsKey()অংশটি বজায় রাখা ভাল ।

আমি আপনার মন্তব্য অনেক প্রশংসা করব।

উত্তর:


112

কিছু মানচিত্র প্রয়োগের নাল মান রাখার অনুমতি দেওয়া হয়, যেমন হ্যাশম্যাপ, যদি এই ক্ষেত্রে get(key)ফিরে আসে nullতবে এই কীটির সাথে জড়িত মানচিত্রে কোনও প্রবেশ নেই বলে গ্যারান্টি দেয় না।

সুতরাং যদি আপনি জানতে চান যে কোনও মানচিত্রে কী ব্যবহার রয়েছে Map.containsKey। আপনার যদি কেবল কী ব্যবহারে মানচিত্রের মানচিত্র প্রয়োজন হয় Map.get(key)। যদি এই মানচিত্রটি নাল মানগুলিকে অনুমতি দেয়, তবে নালটির একটি ফেরতের মান অগত্যা নির্দেশ করে না যে মানচিত্রে কীটির জন্য কোনও ম্যাপিং নেই; এই ক্ষেত্রে Map.containsKeyঅকেজো এবং কর্মক্ষমতা প্রভাবিত করবে। তদুপরি, মানচিত্রে একযোগে অ্যাক্সেসের ক্ষেত্রে (উদাহরণস্বরূপ ConcurrentHashMap), আপনি পরীক্ষা করার পরে Map.containsKey(key)এমন সম্ভাবনা রয়েছে যে আপনি কল করার আগে অন্য থ্রেড দ্বারা প্রবেশিকাটি সরানো হবে Map.get(key)


8
মান সেট করা থাকলেও null, আপনি কি সেটাকে কী / মান দিয়ে আলাদা করে চলাতে চান? আপনার যদি এটির আলাদাভাবে চিকিত্সার প্রয়োজন না হয় তবে আপনি কেবল ব্যবহার করতে পারেনget()
পিটার ল্যারি

4
যদি আপনার Mapহয় private, আপনার শ্রেণি nullমানচিত্রে কখনও প্রবেশ করা হয়নি এমন গ্যারান্টি দিতে সক্ষম হতে পারে । সেক্ষেত্রে আপনি get()নলের জন্য পরিবর্তে চেক ব্যবহার করতে পারেন containsKey()। এটি করা আরও পরিস্কার, এবং কিছু ক্ষেত্রে সম্ভবত আরও কিছুটা দক্ষ হতে পারে।
রায়েডওয়াল্ড

44

আমি মনে করি এটি লেখার পক্ষে মোটামুটি মানসম্পন্ন:

Object value = map.get(key);
if (value != null) {
    //do something with value
}

পরিবর্তে

if (map.containsKey(key)) {
    Object value = map.get(key);
    //do something with value
}

এটি কম পঠনযোগ্য এবং কিছুটা বেশি দক্ষ নয় তাই এটি না করার কোনও কারণ আমি দেখতে পাচ্ছি না। স্পষ্টতই যদি আপনার মানচিত্রে নাল থাকতে পারে তবে দুটি বিকল্পের একই শব্দার্থবিজ্ঞান নেই


8

Asylias হিসাবে ইঙ্গিত, এটি একটি শব্দার্থক প্রশ্ন। সাধারণত, ম্যাপ.জেট (এক্স) == নাল হ'ল আপনি যা চান তা হ'ল, তবে এমন কিছু ক্ষেত্রে রয়েছে যা কন্টিকে কী ব্যবহার করা গুরুত্বপূর্ণ।

এরকম একটি ঘটনা ক্যাশে is আমি একবার একটি ওয়েব অ্যাপ্লিকেশনটিতে এমন একটি পারফরম্যান্স ইস্যুতে কাজ করেছি যা এটির ডাটাবেসগুলি ঘন ঘন জিজ্ঞাসাবাদ করে যা অস্তিত্বহীন সত্তা খুঁজছিল। যখন আমি সেই উপাদানটির জন্য ক্যাচিং কোডটি অধ্যয়ন করেছি, তখন আমি বুঝতে পেরেছিলাম যে cache.get (কী) == নাল থাকলে এটি ডাটাবেসটি অনুসন্ধান করছে। যদি ডাটাবেসটি নাল ফেরায় (সত্তাটি পাওয়া যায় না), তবে আমরা সেই কীটি কেশ করব -> নাল ম্যাপিং।

অন্তর্ভুক্তকিতে স্যুইচিংয়ের ফলে সমস্যার সমাধান হয়েছে কারণ নাল মানটিতে ম্যাপিং আসলে কিছু বোঝায়। নাল থেকে কী ম্যাপিংয়ের কী বিদ্যমান নেই তার চেয়ে আলাদা অর্থপূর্ণ অর্থ ছিল।


মজাদার. ক্যাচিং মানগুলির আগে আপনি কেন কেবল নাল চেক যোগ করলেন না?
সােকেট

এটি কিছুই পরিবর্তন করবে না। পয়েন্ট যে নাল মানে কী ম্যাপিং "আমরা ইতিমধ্যে এই কাজ করেছেন। এটা ক্যাশে আছে। মান হয় নাল"। কোনও প্রদত্ত কীটি একেবারেই না রাখার ভারসাম্য, যার অর্থ "জানি না, ক্যাশে নয়, আমাদের ডিবি পরীক্ষা করতে হবে।"
ব্র্যান্ডন

5
  • containsKeyএকটি getঅপ্রয়োজনীয় কেবল তখনই আমরা যদি এপ্রিওরি জানি যে নাল মান কখনই অনুমোদিত হয় না। যদি নাল মানগুলি বৈধ না হয় তবে এর অনুরোধটির containsKeyএকটি তুচ্ছ কর্মক্ষমতা পেনাল্টি রয়েছে এবং এটি নীচের বেঞ্চমার্কে দেখানো মাত্র ওভারহেড।

  • জাভা 8 Optionalআইডিয়মগুলি - Optional.ofNullable(map.get(key)).ifPresentবা Optional.ofNullable(map.get(key)).ifPresent- কেবল ভ্যানিলা নাল চেকের তুলনায় একটি অ-তুচ্ছ ওভারহেড চাপায়।

  • একটি HashMapএকটি ব্যবহার O(1)ধ্রুবক টেবিল লুকআপ একটি যেহেতু TreeMapব্যবহারসমূহ একটি O(log(n))অনুসন্ধান। containsKeyএকটি দ্বারা অনুসরণ getবাগ্ধারা অনেক ধীর যখন একটি সময় আহবান করা হয় TreeMap

বেঞ্চমার্ক

Https://github.com/vkarun/enum-revers-lookup-table-jmh দেখুন

// t1
static Type lookupTreeMapNotContainsKeyThrowGet(int t) {
  if (!lookupT.containsKey(t))
    throw new IllegalStateException("Unknown Multihash type: " + t);
  return lookupT.get(t);
}
// t2
static Type lookupTreeMapGetThrowIfNull(int t) {
  Type type = lookupT.get(t);
  if (type == null)
    throw new IllegalStateException("Unknown Multihash type: " + t);
  return type;
}
// t3
static Type lookupTreeMapGetOptionalOrElseThrow(int t) {
  return Optional.ofNullable(lookupT.get(t)).orElseThrow(() -> new 
      IllegalStateException("Unknown Multihash type: " + t));
}
// h1
static Type lookupHashMapNotContainsKeyThrowGet(int t) {
  if (!lookupH.containsKey(t))
    throw new IllegalStateException("Unknown Multihash type: " + t);
  return lookupH.get(t);
}
// h2
static Type lookupHashMapGetThrowIfNull(int t) {
  Type type = lookupH.get(t);
  if (type == null)
    throw new IllegalStateException("Unknown Multihash type: " + t);
  return type;
}
// h3
static Type lookupHashMapGetOptionalOrElseThrow(int t) {
  return Optional.ofNullable(lookupH.get(t)).orElseThrow(() -> new 
    IllegalStateException("Unknown Multihash type: " + t));
}
বেঞ্চমার্ক (পুনরাবৃত্তি) (লুকআপপ্রোক্রো) মোড সেন্ট স্কোর ত্রুটি ইউনিট

মাল্টিহ্যাশটাইপলুকআপবিঞ্চমার্ক.টেষ্টলুকআপ 1000 টি 1 গড় 9 33.438 ± 4.514 আমাদের / ওপেন
মাল্টিহ্যাশটাইপলুকআপবিঞ্চমার্ক.টেষ্টলুকআপ 1000 টি 2 গড় 9 26.986 ± 0.405 ইউএস / ওপেন
মাল্টিহ্যাশটাইপলুকআপবিঞ্চমার্ক.টেষ্টলুকআপ 1000 টি 3 গড় 9 39.259 ± 1.306 ইউএস / ওপেন
মাল্টিহ্যাশটাইপলুকআপবিঞ্চমার্ক.টেষ্টলুকআপ 1000 এইচ 1 গড় 9 18.954 ± 0.414 আমাদের / ওপেন
মাল্টিহ্যাশটাইপলুকআপবিঞ্চমার্ক.টেষ্টলুকআপ 1000 এইচ 2 গড় 9 15.486 ± 0.395 ইউএস / ওপেন
মাল্টিহ্যাশটাইপলুকআপবিঞ্চমার্ক.টেষ্টলুকআপ 1000 এইচ 3 গড় 9 16.780 ± 0.719 মার্কিন / ওপেন

ট্রিম্যাপ উত্স রেফারেন্স

https://github.com/openjdk-mirror/jdk7u-jdk/blob/master/src/share/classes/java/util/TreeMap.java

হ্যাশম্যাপ উত্স রেফারেন্স

https://github.com/openjdk-mirror/jdk7u-jdk/blob/master/src/share/classes/java/util/HashMap.java


3

আমরা @Alilias উত্তরটি জাভা 8 বিকল্পের সাথে আরও পঠনযোগ্য করে তুলতে পারি,

Optional.ofNullable(map.get(key)).ifPresent(value -> {
     //do something with value
};)

2

জাভাতে যদি আপনি প্রয়োগটি পরীক্ষা করেন

public boolean containsKey(Object key) {
    return getNode(hash(key), key) != null;
}

public V get(Object key) {
    Node<K,V> e;
    return (e = getNode(hash(key), key)) == null ? null : e.value;
}

উভয়ই মিলটি পুনরুদ্ধার করতে getNode ব্যবহার করে, যেখানে মূল কাজটি সম্পন্ন হয়।

অতিরিক্ত কাজটি উদাহরণস্বরূপ, যদি আপনার কোনও হ্যাশ মানচিত্রে একটি অভিধান থাকে। আপনি যখন কোনও শব্দের অর্থ পুনরুদ্ধার করতে চান

করছি ...

if(dictionary.containsKey(word)) {
   return dictionary.get(word);
}

অপ্রয়োজনীয়।

তবে আপনি যদি একটি শব্দ পরীক্ষা করতে চান তবে এটি অভিধানের ভিত্তিতে বৈধ বা না। করছি ...

 return dictionary.get(word) != null;

শেষ ...

 return dictionary.containsKey(word);

অপ্রয়োজনীয়।

আপনি যদি হ্যাশসেট বাস্তবায়ন যা কিনা অভ্যন্তরীণভাবে হ্যাশম্যাপ ব্যবহার করে তা পরীক্ষা করে থাকেন, তবে 'অন্তর্ভুক্ত' পদ্ধতিতে 'অন্তর্ভুক্তকী' ব্যবহার করুন।

    public boolean contains(Object o) {
        return map.containsKey(o);
    }
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.