2011-11-30 17 views
5

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

ArrayList<Double> list; 
Hashtable<Val,ArrayList<Double>> numbers = new Hashtable<Val,ArrayList<Double>>(); 

while((line = brMyHashval.readLine()) != null) 
{ 
    if(!(line.isEmpty())) 
    {    
     String[] temp; 
     temp = line.split(" ");  
     eDouble = Double.parseDouble(temp[2].toString()); 

     Val key = new Val(Double.parseDouble(temp[0].toString()) ,Double.parseDouble(temp[1].toString())); 

     if(!(numbers.containsKey(key))) 
     { 
      list = new ArrayList<Double>(); 
      numbers.put(key, list); 

     } 
     else 
     { 
      list = numbers.get(key); 
     } 
     list.add(eDouble); 
    } 
} 

मैं इनबिल्ट 'hashCode' के लिए इस्तेमाल किया है और वर्ग की वस्तुओं की तुलना के लिए ग्रहण में विधि 'के बराबर है':

यहाँ मेरी नमूना कोड है।

इनपुट पाठ फ़ाइल:

1.0 2.0 9.0 
3.0 4.0 9.0 
5.0 6.0 9.0 
1.0 2.0 8.0 
5.0 6.0 8.0 
1.0 2.0 7.0 
**7.0 8.0 7.0** // After this point a new hash entry gets added for key(7,8), But key (1,2) get deleted from the hashtable, though count gets increased to 4. 
3.0 4.0 7.0 
5.0 6.0 10.0 
1.0 2.0 10.0 
1.0 3.0 10.0 
1.0 4.0 10.0 

क्यों महत्वपूर्ण यह है कि विशिष्ट पल में नष्ट कर दिया हो जाता है।?

[संपादित करें] hashCode और बराबर होती है: मैं ग्रहण का इस्तेमाल किया स्वचालित रूप से इन तरीकों // (एक्स, वाई) है (ए, बी)

class Val 

{ 
    double x; 
    double y; 

Val(double X, double Y) 
{ 
    x = X; 
    y = Y; 
} 

@Override 
public int hashCode() { 
    final int prime = 31; 
    int result = 1; 
    long temp; 
    temp = Double.doubleToLongBits(x); 
    result = prime * result + (int) (temp^(temp >>> 32)); 
    temp = Double.doubleToLongBits(y); 
    result = prime * result + (int) (temp^(temp >>> 32)); 
    return result; 
} 

@Override 
public boolean equals(Object obj) { 
    if (this == obj) 
     return true; 
    if (obj == null) 
     return false; 
    if (getClass() != obj.getClass()) 
     return false; 
    Val other = (Val) obj; 
    if (Double.doubleToLongBits(x) != Double.doubleToLongBits(other.x)) 
     return false; 
    if (Double.doubleToLongBits(y) != Double.doubleToLongBits(other.y)) 
     return false; 
    return true; 
} 

}

+2

क्या कर अपने hashCode करते हैं और बराबर:

enter image description here

अपने कोड के अंत में निम्नलिखित क्या HashMap में वास्तव में है देखने के लिए जोड़ सकता हूँ? – Thilo

+0

"वैल" कक्षा क्या है? क्या यह "के" जैसा ही है? – dmeister

+0

हाँ। माफ़ कीजिये। वैल क्लास कक्षा के – SyncMaster

उत्तर

6

समस्या यह है कि आप हैश मैप की सामग्री को जांचने के लिए डीबगर का उपयोग कर रहे हैं।

मुझे लगता है कि दोनों कुंजी (1,2) और (7,8) दोनों को सहेजने के लिए उपयोग किए गए हैशटेबल के उसी स्लॉट में सहेजे गए हैं।जैसा कि (7,8) जोड़ा गया है, (1,2) को "बैक" (7,8) में ले जाया गया है - आपको next प्रविष्टि (7,8) प्रविष्टि की जांच करनी होगी।

for (Val key : numbers.keySet()) { 
     System.out.printf("%.1f %.1f: %s%n", key.x, key.y, numbers.get(key)); 
    } 
+1

अच्छी पकड़ है कि हैश मैप का निरीक्षण करने के लिए डीबगर का उपयोग करना सहज नहीं हो सकता है। –

1

यकीन है कि हैश करें और आयात करने के लिए बराबर उनकी आवश्यकताओं को पूरा कर रहे हैं।

प्रत्येक उदाहरण के लिए एक अद्वितीय हैश होना चाहिए और बराबर होना चाहिए तो बराबर होना चाहिए। झूठी सकारात्मक बात यह है कि झूठी सकारात्मक मान एक ही कुंजी के लिए मानचित्र हैं। See this link.

2

ऊपर सुमित्रा का अर्थ है कि आप एक कस्टम क्लास को मानचित्र में एक कुंजी के रूप में उपयोग करना चाहते हैं, तो आपके पास निर्दिष्ट() और हैशकोड() विधियों को निर्दिष्ट के रूप में लिखा जाना चाहिए। (उदाहरण के लिए निम्न कार्य करें:

  • दो कश्मीर वस्तुओं बराबर retuyrn अगर वे एक ही सदस्य हैं
  • दो कश्मीर वस्तुओं एक ही hashCode है अगर वे एक ही सदस्य हैं:

    public boolean equals(K other) { 
        return a == other.a && b == other.b; 
    } 
    
    public int hashCode() { 
        return new Double(a).hashCode()^new Double(b).hashCode(); 
    } 
    

    यह है कि गारंटी देता है

कौन सा नक्शा कुंजी वस्तुओं के लिए एक आवश्यकता है।

+0

यहां तक ​​कि आपके द्वारा उल्लिखित कोड के साथ, वही समस्या होती है। यानी दो के ऑब्जेक्ट अलग-अलग सदस्यों के बराबर लौटते हैं। क्या मुझे विधि को अलग-अलग लिखना चाहिए?^ – SyncMaster

+1

@SyncMaster का उपयोग करते समय भी मुझे अलग-अलग सदस्यों के लिए समान मूल्य क्यों मिलते हैं, इस बात से कोई कारण नहीं मिला कि दो ऑब्जेक्ट्स एक ही 'हैशकोड' वापस कर सकते हैं और फिर भी अलग हो सकते हैं! उदाहरण के लिए स्ट्रिंग्स के पास हैश कोड की तुलना में बहुत अधिक बिट्स हो सकते हैं, प्रत्येक स्ट्रिंग के लिए अद्वितीय अद्वितीय कोड असंभव होंगे। आपके मामले में, दो युगलों में लंबे समय से अधिक बिट्स हैं (हैशकोड रिटर्न प्रकार) –

+0

@ करलोस हेबरर: तो ऐसे मामलों को संभालने का बेहतर तरीका अपना उचित हैशकोड लिख रहा है? – SyncMaster

1

मैं आपकी समस्या को पुन: पेश नहीं कर सकता, यह एक सटीक कोड है जिसे मैं चला रहा हूं (इसे आपके मूल प्रश्न के जितना संभव हो उतना करीब बनाने के अन्य उत्तरों के रूप में सरलीकृत नहीं किया गया है)।

public class HashProblem { 

    public static class Val { 
     private double x; 
     private double y; 

     public Val(double x, double y) { 
      this.x = x; 
      this.y = y; 
     } 

     @Override 
     public int hashCode() { 
      final int prime = 31; 
      int result = 1; 
      long temp; 
      temp = Double.doubleToLongBits(x); 
      result = prime * result + (int) (temp^(temp >>> 32)); 
      temp = Double.doubleToLongBits(y); 
      result = prime * result + (int) (temp^(temp >>> 32)); 
      return result; 
     } 

     @Override 
     public boolean equals(Object obj) { 
      if (this == obj) 
       return true; 
      if (obj == null) 
       return false; 
      if (getClass() != obj.getClass()) 
       return false; 
      Val other = (Val) obj; 
      if (Double.doubleToLongBits(x) != Double.doubleToLongBits(other.x)) 
       return false; 
      if (Double.doubleToLongBits(y) != Double.doubleToLongBits(other.y)) 
       return false; 
      return true; 
     } 
    } 

    public static void main(String... args) throws Exception { 
     ArrayList<Double> list; 
     String line; 
     BufferedReader brMyHashval = new BufferedReader(new InputStreamReader(new FileInputStream("HashProblem.txt"))); 
     Hashtable<Val, ArrayList<Double>> numbers = new Hashtable<Val, ArrayList<Double>>(); 

     while ((line = brMyHashval.readLine()) != null) { 
      if (!(line.isEmpty())) { 
       String[] temp; 
       temp = line.split(" "); 
       Double eDouble = Double.parseDouble(temp[2].toString()); 

       Val key = new Val(Double.parseDouble(temp[0].toString()), Double.parseDouble(temp[1].toString())); 

       if (!(numbers.containsKey(key))) { 
        list = new ArrayList<Double>(); 
        numbers.put(key, list); 
        System.err.println("Created " + key.x + " " + key.y); 
       } else { 
        list = numbers.get(key); 
       } 
       list.add(eDouble); 
       System.err.println("Inserted into " + key.x + " " + key.y + " value " + eDouble + " size " + list.size() + " " + list); 
      } 
     } 
    } 

उत्पादन मैं प्रवेश से प्राप्त

Created 1.0 2.0 
Inserted into 1.0 2.0 value 9.0 size 1 [9.0] 
Created 3.0 4.0 
Inserted into 3.0 4.0 value 9.0 size 1 [9.0] 
Created 5.0 6.0 
Inserted into 5.0 6.0 value 9.0 size 1 [9.0] 
Inserted into 1.0 2.0 value 8.0 size 2 [9.0, 8.0] 
Inserted into 5.0 6.0 value 8.0 size 2 [9.0, 8.0] 
Inserted into 1.0 2.0 value 7.0 size 3 [9.0, 8.0, 7.0] 
Created 7.0 8.0 
Inserted into 7.0 8.0 value 7.0 size 1 [7.0] 
Inserted into 3.0 4.0 value 7.0 size 2 [9.0, 7.0] 
Inserted into 5.0 6.0 value 10.0 size 3 [9.0, 8.0, 10.0] 
Inserted into 1.0 2.0 value 10.0 size 4 [9.0, 8.0, 7.0, 10.0] 
Created 1.0 3.0 
Inserted into 1.0 3.0 value 10.0 size 1 [10.0] 
Created 1.0 4.0 
Inserted into 1.0 4.0 value 10.0 size 1 [10.0] 

है नहीं है कि तुम क्या उम्मीद थी है?

अन्य उत्तरों में आपके हैशकोड को सरल बनाने और बराबर करने के बारे में अच्छे अंक हैं। साथ ही, आपको ऑब्जेक्ट पर स्ट्रिंग() करने की आवश्यकता नहीं है जो पहले से तार हैं।