2012-02-24 13 views
6

तो मेरे पास एक बहुत ही अजीब बग है। जब मैं मूल रूप से एक बड़े ट्रीमैप की पहली 10 कुंजी पर फिर से शुरू करने के लिए एक कुंजीसेट() का उपयोग कर रहा था, तो मैं उस पर ठोकर खाई। चाबियों में से एक शून्य वापस लौट रहा था, जहां तक ​​मेरी समझ पूरी हो सकती है। तो मैं नीचे परीक्षण कोड लिखा है:ट्री मैप में कुंजी शून्य लौट रहा है

int i = 0; 
     for (Map.Entry<String, Integer> es : sortedMap.entrySet()){ 
      if (i >= 10) { 
       break; 
      } 

      if (sortedMap.containsKey(es.getKey())){ 
       System.out.println(es.getKey() + ":" + sortedMap.get(es.getKey())); 
      } else { 
       System.out.println("Key " + es.getKey() + " does not exist, yet..."); 
       System.out.println("This does work: " + es.getKey() + ":" + es.getValue()); 
       System.out.println("This does NOT work: " + es.getKey() + ":" + sortedMap.get(es.getKey())); 
      } 
      i++; 
     } 

और मिल निम्न परिणाम:

SOAP:967 
'excerpt'::679 
'type'::679 
Key 'author_url': does not exist, yet... 
This does work: 'author_url'::679 
This does NOT work: 'author_url'::null 
'date'::679 
Android:437 
TLS:295 
message:283 
server:230 
monthly:215 
<<<<<<<<<<<<<<<<<<<<DUMPING MAP! 
{SOAP=967, 'excerpt':=679, 'type':=679, 'author_url':=679, 'date':=679, Android=437, TLS=295, message=283, server=230, monthly=215... 

मैं शीर्ष दस के बाद नक्शा काट के रूप में वहाँ है वहाँ में एक बहुत अधिक है, लेकिन यह के सभी एक मूल्य के साथ एक कुंजी है।

तो मेरा सवाल यह है: ट्रीमैप से सीधे (कुंजी) प्राप्त करने के लिए कुंजी का उपयोग करते समय मुझे शून्य क्यों मिल रहा है, लेकिन EntrySet सही कुंजी और मान देता है?

यहाँ मेरी तुलनित्र के बाद से मैं पूर्णांक पर आदेश देने से कर रहा हूँ:

class ValueComparator implements Comparator<Object> { 

    Map<String, Integer> base; 
    public ValueComparator(Map<String, Integer> base) { 
     this.base = base; 
    } 

    public int compare(Object a, Object b) { 

    if ((Integer) base.get(a) < (Integer) base.get(b)) { 
     return 1; 
    } else if ((Integer) base.get(a) == (Integer) base.get(b)) { 
     return 0; 
    } else { 
     return -1; 
    } 
    } 
} 

और ट्री-मैप निम्नलिखित के रूप में बनाया गया है:

ValueComparator bvc = new ValueComparator(allMatches); 
TreeMap<String, Integer> sortedMap = new TreeMap<String, Integer>(bvc); 
//Sort the HashMap 
sortedMap.putAll(allMatches); 

कहाँ allMatches एक HashMap<String, Integer>

+4

आप ट्री-मैप के लिए एक असामान्य तुलनित्र का उपयोग कर रहे हैं? यदि हां, तो क्या हम इसका कोड देख सकते हैं? यह आपके डंप से दिखता है जैसे कि आप डिफ़ॉल्ट 'स्ट्रिंग' ऑर्डरिंग का उपयोग नहीं कर रहे हैं ... –

+0

@LouisWasserman मेरे तुलनित्र को जोड़ा गया। –

+2

आपके पास उस कक्षा में एक निर्माता और सदस्य क्यों है? तुलनित्र को सामान्य रूप से प्रत्येक तत्व के लिए बुलाया जाता है ताकि आपको परिणामस्वरूप मानचित्र का संदर्भ नहीं देना चाहिए। आपका पूरा कोड उपयोगी होगा। – tom

उत्तर

1

समस्या हल:

class ValueComparator implements Comparator<Object> { 

Map<String, Integer> base; 

public ValueComparator(Map<String, Integer> base) { 
    this.base = base; 
} 

public int compare(Object a, Object b) { 

    if (((Integer) base.get(a)).intValue() < ((Integer) base.get(b)).intValue()) { 
     return 1; 
    } else if (((Integer) base.get(a)).intValue() == ((Integer) base.get(b)).intValue()) { 
     return ((String)a).compareTo(((String)b)); 
    } else { 
     return -1; 
    } 
} 
} 

class ValueComparator implements Comparator<Integer> { 


    public int compare(Integer a, Integer b) { 
     return a.compareTo(b); 
    } 
} 

इसके बाद आप तुलनित्र के साथ अपने ट्री-मैप को प्रारंभ और अपने सभी आइटम जोड़ने की जरूरत

यह वापस लाने के अतिरिक्त लाभ के साथ आता है वर्णमाला क्रम में एक ही मान के साथ eys।

7
के आदेश से

है अपने TreeMap शो को पुनरावृत्ति दिखाएं, यह निश्चित रूप से यह मामला है कि आपने कस्टम Comparator का उपयोग किया था। कि javadocs के अनुसार [अन्यथा यात्रा lexicographical क्रम में हो गया होता]

नोट:

implementor कि sgn (तुलना (एक्स, वाई)) == -sgn (तुलना यह सुनिश्चित करना चाहिए (y , एक्स)) सभी एक्स और वाई के लिए। (यह है कि (एक्स, वाई) की तुलना यदि और केवल यदि तुलना (y, x) एक अपवाद फेंकता एक अपवाद फेंक चाहिए निकलता है।)

implementor भी सुनिश्चित करना चाहिए कि संबंध सकर्मक है: ((तुलना (एक्स, वाई)> 0) & & (तुलना करें (वाई, जेड)> 0)) तुलना (x, z)> 0 की तुलना करें)।

अंत में, कार्यान्वयनकर्ता को यह सुनिश्चित करना चाहिए कि तुलना करें (x, y) == 0 का अर्थ है जो sgn (तुलना (x, z)) == sgn (तुलना करें (y, z)) सभी z के लिए।

यदि आपका Comparator इन नियमों को लागू नहीं करता है - व्यवहार परिभाषित नहीं किया गया है, जैसा कि आप देखते हैं अजीब परिणाम दिखा सकते हैं।

संपादित करें: [उसे संपादित सवाल के जवाब के रूप में]
आपका compartor पहचान [operator==] दो पूर्णांकों की जाँच करने का उपयोग करता है।
ध्यान दें कि Integer एक वस्तु है - और इस प्रकार operator== केवल true वापस लौटाएगा यदि यह वही वस्तु है।या और भी बेहतर - -
आप अगर दो पूर्णांकों समान हैं की जाँच करने के equals() का उपयोग करना चाहिए का उपयोग Integer.compareTo()

+0

तुलना का उपयोग करने के कारण ट्रीएप बराबर के किसी भी मूल्य पर पतन का कारण बनता है। '{मासिक = 215, सर्वर = 230, संदेश = 283, टीएलएस = 295, एंड्रॉयड = 475, अंश = 679, सोप = 967}' –

+0

दरअसल, और कहा कि एक संकेत है कि अपने कोड और भी टूट गया है है। आप 'TreeMap' का बिल्कुल भी उपयोग नहीं कर सकते, ऐसा नहीं है कि आप इसका उपयोग करने का प्रयास कर रहे हैं। –

+0

@ डेनिस सुलिवान: लुई ने जो कहा उसके अलावा: संलग्न जावा दस्तावेज़ पढ़ें। आपको यह सुनिश्चित करना होगा कि आपका तुलनाकर्ता लिखित शर्तों को पूरा करता है - अन्यथा व्यवहार परिभाषित नहीं किया गया है। – amit

3

आपकी सबसे बड़ी समस्या यह है कि अपने == की बजाय अपने मूल्य तुलनित्र में .equals उपयोग बातें टूट रहा है, क्योंकि अलग कुंजी मैप किया जा रहा है है अलग-अलग Integer ऑब्जेक्ट्स के साथ intValue(), जो अप्रत्याशित रूप से और भी चीजों को फेंक रहा है।

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

एक बेहतर समाधान this की तरह कुछ हो सकता है, लेकिन मूल रूप से, आप मूल्यों से छँटाई के बिना मानचित्र में भरना चाहिए entrySet सॉर्ट, और फिर प्रविष्टियों के पास नक्शे की LinkedHashMap कि जरूरत नहीं है की तरह नकल (क्रम में) एक तुलनित्र, लेकिन प्रविष्टि के क्रम में केवल प्रविष्टियां रखता है।

आपके तुलनित्र को बदलने में सक्षम हो ताकि यदि मान समान हों, तो यह कुंजी की तुलना भी करेगा। यह कम से कम आप एक ही मूल्य के साथ कई चाबियाँ सम्मिलित करते हैं ... लेकिन यह अभी भी एक बहुत hacky समाधान के रूप में ऊपर वर्णित एक LinkedHashMap आधारित समाधान की तुलना में काफी जोखिम भरी है कि है।

+0

ऊपर सही जवाब पर पहुंचने की सोच की मेरी लाइन की मदद करने के लिए वोट दिया गया। –

0

आप बस होना चाहिए:

Treemap

+0

वह इसे उपयोग कर रहा है मान है, जो एक 'TreeMap' के साथ काम करने नहीं जा रहा है की तुलना करने, वास्तव में नहीं = ( –

+0

आप ठीक कह रहे हैं।मैं चाहता हूं कि वह चाबियाँ (हमेशा की तरह) पर छंटनी कर रहा था लेकिन वह मूल्यों पर छंटाई कर रहा है। मैंने सवाल गलत तरीके से पढ़ा। मैं बस इतना कह सकता हूं कि मूल्यों पर छंटनी सामान्य रूप से मानचित्र में नहीं की जाती है। सूची इसके लिए बेहतर अनुकूल हैं। – tom

संबंधित मुद्दे