क्या होता है जब एक डुप्लिकेट कुंजी को हैशपॉप में डाला जाता है?


276

अगर मैं करने के लिए एक ही कुंजी कई बार पारित HashMapकी putविधि, क्या मूल मूल्य का क्या होगा? और क्या होगा अगर मूल्य भी दोहराता है? मुझे इस पर कोई दस्तावेज नहीं मिला।

केस 1: एक कुंजी के लिए ओवरराइट किए गए मान

Map mymap = new HashMap();
mymap.put("1","one");
mymap.put("1","not one");
mymap.put("1","surely not one");
System.out.println(mymap.get("1"));

हमें मिलता है surely not one

केस 2: डुप्लिकेट मान

Map mymap = new HashMap();
mymap.put("1","one");
mymap.put("1","not one");
mymap.put("1","surely not one");
// The following line was added:
mymap.put("1","one");
System.out.println(mymap.get("1"));

हमें मिलता है one

लेकिन अन्य मूल्यों का क्या होता है? मैं एक छात्र को मूल बातें सिखा रहा था और मुझसे यह पूछा गया। क्या Mapएक बाल्टी की तरह जहां अंतिम मान संदर्भित है (लेकिन स्मृति में)?


7
BTW, यह जकार्ता कलेक्शन क्लासेज ( commons.apache.org/collections ) का हिस्सा है मल्टी-हैशमैप को दिखाने का एक शानदार अवसर है । यह आपको उस समय के लिए एक ही कुंजी के साथ जुड़े किसी भी मूल्य की आवश्यकता होगी जब आपको इसकी आवश्यकता होगी।
जॉन मुंसच

जवाबों:


303

परिभाषा के अनुसार, putकमांड मैप में दी गई कुंजी से संबंधित पिछले मूल्य को बदल देता है (वैचारिक रूप से आदिम प्रकारों के लिए एक सरणी अनुक्रमण ऑपरेशन की तरह)।

मानचित्र केवल मूल्य के संदर्भ को छोड़ देता है। यदि और कुछ भी वस्तु का संदर्भ नहीं रखता है, तो वह वस्तु कचरा संग्रहण के योग्य हो जाती है। इसके अतिरिक्त, जावा दी गई कुंजी (या nullयदि कोई मौजूद नहीं है) के साथ जुड़े किसी भी पिछले मूल्य को वापस करता है , तो आप यह निर्धारित कर सकते हैं कि क्या था और यदि आवश्यक हो तो एक संदर्भ बनाए रखें।

अधिक जानकारी यहाँ: HashMap डॉक्टर


इसके लिए धन्यवाद। पढ़ना हालांकि जावा प्रलेखन यह स्पष्ट रूप से उल्लेख नहीं किया गया है। मैं अनुमान लगा रहा हूं कि डॉक्टर के लेखक ने इसे सभी हैश मानचित्र कार्यान्वयन की एक मौन धारणा माना है।
एंड्रयू एस

77

आपको अपना उत्तर मानचित्र के पुट # पुट (K, V) में मिल सकता है (जो वास्तव में कुछ देता है):

public V put(K key,
             V value)

इस नक्शे में निर्दिष्ट कुंजी के साथ निर्दिष्ट मूल्य को जोड़ता है (वैकल्पिक संचालन)। यदि मानचित्र में पहले इस कुंजी के लिए मैपिंग शामिल है, तो पुराने मान को निर्दिष्ट मान से बदल दिया जाता है। (एक नक्शे mमें कहा जाता है कि kयदि कोई कुंजी के लिए मानचित्रण सम्‍मिलित करता है, केवल और यदि m.containsKey(k)वह वापस लौटता है true।)

पैरामीटर:
key - वह कुंजी जिसके साथ निर्दिष्ट मूल्य जुड़ा होना है।
value- निर्दिष्ट कुंजी के साथ जुड़े होने का मूल्य।

रिटर्न:
निर्दिष्ट कुंजी के साथ जुड़ा हुआ पिछला मान, या nullयदि कोई मैपिंग नहीं थी key। ( nullवापसी यह भी संकेत कर सकती है कि पहले nullनिर्दिष्ट के साथ जुड़ा हुआ मानचित्र key, यदि कार्यान्वयन nullमूल्यों का समर्थन करता है।)

इसलिए यदि आप कॉल करते समय लौटाया गया मान असाइन नहीं करते हैं mymap.put("1", "a string"), तो यह अप्रतिबंधित हो जाता है और इस प्रकार कचरा संग्रहण के लिए पात्र हो जाता है।


3
दिए गए मान है पिछले मान (या nullतो, हाँ, यह मैं क्या मतलब है) के रूप में सिर्फ जावाडोक में ऊपर से प्रलेखित। क्या सच में इसका गलत मतलब निकाला जा सकता है?
पास्कल थिवेंट

यह बहुत मददगार है।
रोज़ट्रेलर

18

कुंजी के लिए पूर्व मान गिरा दिया गया है और नए के साथ बदल दिया गया है।

यदि आप उन सभी मूल्यों को रखना चाहते हैं जो एक कुंजी दी गई है, तो आप कुछ इस तरह से लागू करने पर विचार कर सकते हैं:

import org.apache.commons.collections.MultiHashMap;
import java.util.Set;
import java.util.Map;
import java.util.Iterator;
import java.util.List;
public class MultiMapExample {

   public static void main(String[] args) {
      MultiHashMap mp=new MultiHashMap();
      mp.put("a", 10);
      mp.put("a", 11);
      mp.put("a", 12);
      mp.put("b", 13);
      mp.put("c", 14);
      mp.put("e", 15);
      List list = null;

      Set set = mp.entrySet();
      Iterator i = set.iterator();
      while(i.hasNext()) {
         Map.Entry me = (Map.Entry)i.next();
         list=(List)mp.get(me.getKey());

         for(int j=0;j<list.size();j++)
         {
          System.out.println(me.getKey()+": value :"+list.get(j));
         }
      }
   }
}

1
यह समाधान वंचित है। MultiHashMap apache.commons.collections का हिस्सा है और जावा नहीं।
विकिमिक्स

17

यह कुंजी / मूल्य विशेषता है और आप कई मूल्यों के लिए डुप्लिकेट कुंजी नहीं रख सकते हैं क्योंकि जब आप वास्तविक मूल्य प्राप्त करना चाहते हैं, जो कि मूल्यों में से एक
आपके उदाहरण में दर्ज की गई कुंजी से संबंधित है जब आप "1" का मूल्य प्राप्त करना चाहते हैं जो एक है यह!
हर मूल्य के लिए अद्वितीय कुंजी होने का कारण है, लेकिन आपको java मानक के हिसाब से चाल चलनी चाहिए:

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

public class DuplicateMap<K, V> {

    private Map<K, ArrayList<V>> m = new HashMap<>();

    public void put(K k, V v) {
        if (m.containsKey(k)) {
            m.get(k).add(v);
        } else {
            ArrayList<V> arr = new ArrayList<>();
            arr.add(v);
            m.put(k, arr);
        }
    }

     public ArrayList<V> get(K k) {
        return m.get(k);
    }

    public V get(K k, int index) {
        return m.get(k).size()-1 < index ? null : m.get(k).get(index);
    }
}


और आप इसे इस तरह से उपयोग कर सकते हैं:

    public static void main(String[] args) {
    DuplicateMap<String,String> dm=new DuplicateMap<>();
    dm.put("1", "one");
    dm.put("1", "not one");
    dm.put("1", "surely not one");
    System.out.println(dm.get("1"));
    System.out.println(dm.get("1",1));
    System.out.println(dm.get("1", 5));
}

और प्रिंट के परिणाम हैं:

[one, not one, surely not one]
not one
null

बहुत बढ़िया जवाब! बहुत बढ़िया। तुम सचमुच मेरे प्रोग्रामिंग जीवन को बचाओ :)।
सुबिन बाबू

मुझे भी धन्यवाद! मुझे एक सामान्य मानचित्र के समान कार्यक्षमता करने के लिए इसमें "रिमूव" मेथड जोड़ना पड़ा लेकिन बहुत बढ़िया काम किया!
जेग्लास

1
@ अपने स्वागत यश को समझें, लेकिन यह तकनीकी समाधान नहीं है, यह है कि आप जावा मानक लिब द्वारा क्या कर सकते हैं, तकनीकी रूप से समस्या में आपको अपनी समस्या पर ध्यान देना चाहिए, यदि आपको यह व्यवहार करने की आवश्यकता है, तो मुझे यकीन है कि इसका समाधान नहीं है क्योंकि कुंजी / मूल्य अवधारणा की, और समस्या के बारे में सोचना चाहिए और हल करने के लिए तार्किक तरीका खोजना चाहिए। वैसे भी मेरा विवरण जावा के साथ करने के लिए सिर्फ मजेदार तरीका है और उत्पादन, समस्याओं और समाधान के मार्ग मजेदार काम के लिए बहुत अलग है! लेकिन आप इसका उपयोग तब कर सकते हैं जब कुंजी / मान व्यवहार आपकी समस्या नहीं है और उस जैसी डेटा संरचना प्राप्त करना है।
जावा एकम

13

इस नक्शे में निर्दिष्ट कुंजी के साथ निर्दिष्ट मान संबद्ध करता है। यदि मानचित्र में पहले कुंजी के लिए मैपिंग शामिल है, तो पुराने मान को बदल दिया जाता है।


12

यह संबंधित कुंजी के लिए मानचित्र में मौजूदा मूल्य को बदल देता है । और अगर कोई कुंजी समान नाम के साथ मौजूद नहीं है, तो यह प्रदान की गई मूल्य के साथ एक कुंजी बनाता है। उदाहरण के लिए:

Map mymap = new HashMap();
mymap.put("1","one");
mymap.put("1","two");

आउटपुट कुंजी = "1", मूल्य = "दो"

इसलिए, पिछला मान अधिलेखित हो जाता है।


4

आपके प्रश्न के लिए कि क्या नक्शा एक बाल्टी की तरह था: नहीं।

यह name=valueजबकि जोड़े के साथ एक सूची की तरह हैname एक स्ट्रिंग होने की आवश्यकता नहीं है (यह कर सकते हैं, हालांकि)।

एक तत्व प्राप्त करने के लिए, आप अपनी कुंजी को प्राप्त करने के लिए पास करते हैं () - विधि जो आपको बदले में सौंपी गई वस्तु देती है।

और हैश मैप का अर्थ है कि यदि आप गेट -मेथड का उपयोग करके अपनी वस्तु को पुनः प्राप्त करने का प्रयास कर रहे हैं, तो यह आपके द्वारा प्रदान की गई वास्तविक वस्तु की तुलना नहीं करेगा, क्योंकि इसे अपनी सूची के माध्यम से पुनरावृत्ति करना होगा और () की तुलना करना होगा आपने वर्तमान तत्व प्रदान किया है।

यह अक्षम्य होगा। इसके बजाय, आपकी वस्तु में कोई फर्क नहीं पड़ता, यह दोनों वस्तुओं से तथाकथित हैशकोड की गणना करता है और उन की तुलना करता है। दो की तुलना करना आसान हैintदो पूरे (संभवतः गहरे जटिल) वस्तुओं के बजाय एस की । आप एक पूर्वनिर्धारित लंबाई (int) वाले सारांश की तरह हैशकोड की कल्पना कर सकते हैं, इसलिए यह अद्वितीय नहीं है और इसमें टक्कर हैं। आपने दस्तावेज़ में हैशकोड के नियम खोजे हैं जिनमें मैंने लिंक डाला है।

यदि आप इसके बारे में अधिक जानना चाहते हैं, तो आप javapractices.com और technofundo.com पर लेख देख सकते हैं

सादर


3

मैंने हमेशा इस्तेमाल किया:

HashMap<String, ArrayList<String>> hashy = new HashMap<String, ArrayList<String>>();

अगर मैं एक पहचान कुंजी के लिए कई चीजें लागू करना चाहता था।

public void MultiHash(){
    HashMap<String, ArrayList<String>> hashy = new HashMap<String, ArrayList<String>>();
    String key = "Your key";

    ArrayList<String> yourarraylist = hashy.get(key);

    for(String valuessaved2key : yourarraylist){
        System.out.println(valuessaved2key);
    }

}

आप हमेशा कुछ ऐसा कर सकते हैं और अपने आप को एक भूलभुलैया बना सकते हैं!

public void LOOK_AT_ALL_THESE_HASHMAPS(){
    HashMap<String, HashMap<String, HashMap<String, HashMap<String, String>>>> theultimatehashmap = new HashMap <String, HashMap<String, HashMap<String, HashMap<String, String>>>>();
    String ballsdeep_into_the_hashmap = theultimatehashmap.get("firststring").get("secondstring").get("thirdstring").get("forthstring");
}

2

डुप्लिकेट कीज़ के तहत डेटा स्टोर करने के लिए JDK से मैप्स नहीं हैं

  • सबसे अच्छा नया मूल्य पिछले वाले को ओवरराइड करेगा।

  • बदतर परिदृश्य अपवाद है (जैसे जब आप इसे एक धारा के रूप में इकट्ठा करने की कोशिश करते हैं):

कोई डुप्लिकेट नहीं:

Stream.of("one").collect(Collectors.toMap(x -> x, x -> x))

ठीक। आपको मिलेगा: $ 2 ==> {एक = एक}

डुप्लीकेट स्ट्रीम:

Stream.of("one", "not one", "surely not one").collect(Collectors.toMap(x -> 1, x -> x))

अपवाद java.lang.IllegalStateException: डुप्लिकेट कुंजी 1 (मानों को एक और एक में विलय करने का प्रयास किया गया है)। कलेक्टरों पर ।.dlicateKeyException (कलेक्टरों। java: 133) | संग्राहक पर जायें। लेम्बडा $ uniqKeysMapAccumulator $ 1 (कलेक्टर। जावा: 180) | ReduceOps में $ 3ReducingSink.accept (ReduceOps.java:169) | Spliterators पर $ ArraySpliterator.forEachRemaining (Spliterators.java:948) | पर AbstractPipeline.copyInto (AbstractPipeline.java:484) | At AbstractPipeline.wrapAndCopyInto (AbstractPipeline.java:474) | at ReduceOps $ ReduceOp.ev मूल्यांकनSentialential (ReduceOps.java:913) | at AbstractPipeline.ev मूल्यांकन (AbstractPipeline.java:234) | at ReferencePipeline.collect (रेफरेंसपिपलीन.जवा .78) | (# 4: 1) पर

डुप्लिकेट कीज़ से निपटने के लिए - अन्य पैकेज का उपयोग करें, जैसे: https://google.github.io/guava/releases/19.0/api/docs/com/google/common/collect/Multimap.html

डुप्लिकेट कीज़ से निपटने के लिए कई अन्य कार्यान्वयन हैं। वे वेब के लिए आवश्यक हैं (उदाहरण के लिए डुप्लिकेट कुकी कुंजी, Http हेडर समान फ़ील्ड हो सकते हैं, ...)

सौभाग्य! :)


क्या "ओवरराइड" ऑपरेशन महंगा है?
गौरव

इसे केवल JDK के उपयोग से हल किया जा सकता है। Collectors.toMap()तीसरा तर्क है - मर्ज फ़ंक्शन। अगर हम केवल अंतिम डुप्लिकेट तत्व को ओवरराइड करना चाहते हैं Stream.of("one", "two", "one").collect(Collectors.toMap(x -> x, x -> x, (key1, key2) -> key2)):। लिंक
अकेले

साथ ही आपका दूसरा कोड उदाहरण भी सही नहीं है। यह इनपुट: "one", "not one", "surely not one"अलग-अलग सभी स्ट्रिंग्स के कारण कोई डुप्लिकेट कुंजी त्रुटियों का उत्पादन नहीं करेगा।
अकेले

हाय @ अकेले समझो। कृपया मैपिंग फ़ंक्शन (toMap) को ध्यान से पढ़ें।
विटोल कोकज़ुरबा

हाय @WitoldKaczurba। कृपया पोस्ट करने से पहले अपना कोड संकलित करें।
अकेले खड़े

1

BTW, यदि आप कुछ शब्दार्थ चाहते हैं जैसे कि यदि यह कुंजी मौजूद नहीं है। आप फ़ंक्शन के concurrentHashMapसाथ उपयोग कर सकते हैं putIfAbsent()। इसकी जांच करें:

https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ConcurrentHashMap.html#put(K,%20V)

concurrentHashMap उच्च प्रदर्शन के साथ थ्रेड सुरक्षित है क्योंकि यह थ्रूपुट को बेहतर बनाने के लिए " लॉक स्ट्रिपिंग " तंत्र का उपयोग करता है ।


1

हां, इसका मतलब है कि मूल्य के साथ सभी 1 कुंजी अंतिम जोड़े गए मूल्य के साथ ओवरराइट हैं और यहां आप "निश्चित रूप से एक नहीं" जोड़ते हैं, इसलिए यह केवल "निश्चित रूप से एक नहीं" प्रदर्शित करेगा।

यहां तक ​​कि अगर आप एक लूप के साथ प्रदर्शित करने की कोशिश कर रहे हैं, तो यह केवल एक कुंजी और मूल्य भी प्रदर्शित करेगा जिसमें एक ही कुंजी है।


0
         HashMap<Emp, Emp> empHashMap = new HashMap<Emp, Emp>();

         empHashMap.put(new Emp(1), new Emp(1));
         empHashMap.put(new Emp(1), new Emp(1));
         empHashMap.put(new Emp(1), new Emp());
         empHashMap.put(new Emp(1), new Emp());
         System.out.println(empHashMap.size());
    }
}

class Emp{
    public Emp(){   
    }
    public Emp(int id){
        this.id = id;
    }
    public int id;
    @Override
    public boolean equals(Object obj) {
        return this.id == ((Emp)obj).id;
    }

    @Override
    public int hashCode() {
        return id;
    }
}


OUTPUT : is 1

मतलब हैश मैप न तो डुप्लिकेट की अनुमति देता है, अगर आपने ठीक से बराबरी और हैशकोड () विधियों को ओवरराइड किया है।

HashSet आंतरिक रूप से HashMap का उपयोग करता है, स्रोत डॉक्टर देखें

public class HashSet{
public HashSet() {
        map = new HashMap<>();
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.