2009-12-10 7 views
7

में चलाया जाता है मेरे पास एक ऐसा एप्लिकेशन है जो पंक्तियों, ऑब्जेक्ट = एक पंक्ति में ऑब्जेक्ट्स का संग्रह प्रदर्शित करता है। वस्तुओं को हैश मैप में संग्रहीत किया जाता है। पंक्तियों का क्रम एप्लिकेशन की कार्यक्षमता को प्रभावित नहीं करता है (यही कारण है कि एक क्रमबद्ध संग्रह के बजाय हैश मैप का उपयोग किया गया था)।हैश मैप में आइटम्स का ऑर्डर भिन्न होता है जब एक ही प्रोग्राम JVM5 बनाम JVM6

हालांकि मैंने देखा है कि जावा वर्चुअल मशीन के दो अलग-अलग संस्करणों का उपयोग करते समय एक ही एप्लिकेशन अलग-अलग चलता है। आवेदन जेडीके 5 का उपयोग करके संकलित किया गया है, और किसी भी कार्यात्मक अंतर के बिना जावा 5 या जावा 6 रनटाइम्स का उपयोग करके चलाया जा सकता है।

प्रश्न में ऑब्जेक्ट java.lang.Object#hashCode() ओवरराइड करता है और स्पष्ट रूप से जावा एपीआई में निर्दिष्ट अनुबंध का पालन करने के लिए देखभाल की जाती है। यह इस तथ्य से प्रमाणित है कि वे हमेशा आवेदन के हर भाग (उसी जावा रनटाइम में) में उसी क्रम में दिखाई देते हैं।

जिज्ञासा के लिए, जावा रनटाइम की पसंद ऑर्डर को क्यों प्रभावित करती है?

+2

('लिंक्ड हैशमैप 'आपको एक सतत आदेश दे सकता है।) –

उत्तर

17

HashMap का कार्यान्वयन विवरण बदल सकता है और बदल सकता है। सबसे अधिक संभावना इस पैकेज निजी विधि था (यह JDK 1.6.0_16 से है):

/** 
* Applies a supplemental hash function to a given hashCode, which 
* defends against poor quality hash functions. This is critical 
* because HashMap uses power-of-two length hash tables, that 
* otherwise encounter collisions for hashCodes that do not differ 
* in lower bits. Note: Null keys always map to hash 0, thus index 0. 
*/ 
static int hash(int h) { 
    // This function ensures that hashCodes that differ only by 
    // constant multiples at each bit position have a bounded 
    // number of collisions (approximately 8 at default load factor). 
    h ^= (h >>> 20)^(h >>> 12); 
    return h^(h >>> 7)^(h >>> 4); 
} 

संदर्भ के लिए, JDK 1.5.0_06 में एनालॉग है:

/** 
* Returns a hash value for the specified object. In addition to 
* the object's own hashCode, this method applies a "supplemental 
* hash function," which defends against poor quality hash functions. 
* This is critical because HashMap uses power-of two length 
* hash tables.<p> 
* 
* The shift distances in this function were chosen as the result 
* of an automated search over the entire four-dimensional search space. 
*/ 
static int hash(Object x) { 
    int h = x.hashCode(); 

    h += ~(h << 9); 
    h ^= (h >>> 14); 
    h += (h << 4); 
    h ^= (h >>> 10); 
    return h; 
} 
+2

+1; माइकल, मैंने बिंदु को चित्रित करने के लिए जेडीके 5 से समकक्ष कोड जोड़ा है; अगर आपको लगता है कि यह आपके उत्तर में उपयुक्त नहीं है तो मेरे संपादन को वापस लाएं। –

+0

+1 .... क्या मैं एंड्रज को भी वोट दे सकता हूं? :) – skaffman

+0

नहीं, यह वही है जो मैं खोदने के लिए बहुत आलसी था, हाथ में 1.5 जेडीके नहीं था। –

10

शायद क्योंकि Map किसी विशेष पुनरावृत्ति आदेश के लिए परिभाषित नहीं किया गया है; जिस क्रम में तत्व वापस आते हैं, वह आंतरिक कार्यान्वयन का एक आर्टिफैक्ट होने की संभावना है और इसे लगातार रहने की आवश्यकता नहीं है।

यदि कार्यान्वयन जावा 5 और 6 (विशेष रूप से प्रदर्शन कारणों के लिए) के बीच अपडेट हो जाता है, तो यह सुनिश्चित करने के लिए सूर्य का कोई लाभ या दायित्व नहीं है कि पुनरावृत्ति आदेश दोनों के बीच सुसंगत रहता है।

संपादित: मैं बस जल्दी जावा 6 विज्ञप्ति में से एक (दुर्भाग्य से मैं सही संस्करण के बारे में सुनिश्चित नहीं कर रहा हूँ, लेकिन यह जून से जाहिरा तौर पर HashMap 1.68 है 2006) में एक दिलचस्प स्निपेट नहीं मिली:

/** 
    * Whether to prefer the old supplemental hash function, for 
    * compatibility with broken applications that rely on the 
    * internal hashing order. 
    * 
    * Set to true only by hotspot when invoked via 
    * -XX:+UseNewHashFunction or -XX:+AggressiveOpts 
    */ 
private static final boolean useNewHash; 
static { useNewHash = false; } 

private static int oldHash(int h) { 
    h += ~(h << 9); 
    h ^= (h >>> 14); 
    h += (h << 4); 
    h ^= (h >>> 10); 
    return h; 
} 

private static int newHash(int h) { 
    // This function ensures that hashCodes that differ only by 
    // constant multiples at each bit position have a bounded 
    // number of collisions (approximately 8 at default load factor). 
    h ^= (h >>> 20)^(h >>> 12); 
    return h^(h >>> 7)^(h >>> 4); 
} 

तो ऐसा लगता है कि मेरे उपरोक्त दावों के बावजूद, सूर्य वास्तव में पुनरावृत्ति आदेश की स्थिरता पर विचार करता था - कुछ समय बाद इस कोड को संभवतः गिरा दिया गया था और नए आदेश ने निश्चित किया।

+0

हाँ, मुझे वह पता था। अगर आदेश मेरे लिए मायने रखता है, तो मैं एक और प्रकार का संग्रह चुनता था जिसमें ऑर्डर संरक्षित होता है। मैं सिर्फ इतना उत्सुक था कि क्यों। संपादन के लिए +1 @Michael Borgwardt' के उत्तर – bguiz

0

HashMap किसी विशेष से शादी नहीं है आदेश, लेकिन LinkedHashMap मानचित्र के कार्यान्वयन को आदेश को संरक्षित करना चाहिए।

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