2009-08-24 11 views
22

के साथ हैश मैप का प्रदर्शन यहां मेरी स्थिति है। मैं दो java.util.HashMap का उपयोग कर रहा हूं ताकि टॉमकैट पर चल रहे जावा वेब ऐप में कुछ बार इस्तेमाल किए गए डेटा को स्टोर किया जा सके। मुझे प्रत्येक हैशमैप में प्रविष्टियों की सटीक संख्या पता है। चाबियां तार क्रमशः, और स्याही होगी।विभिन्न प्रारंभिक क्षमता और लोड फैक्टर

मेरा सवाल है, आरंभिक क्षमता और लोडफैक्टर सेट करने का सबसे अच्छा तरीका क्या है?

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

मान लीजिए (और यह एक खिंचाव है) हैश फ़ंक्शन पूर्णांक कुंजी का एक साधारण मोड 5 है, इसका मतलब यह नहीं होगा कि कुंजी 5, 10, 15 एक ही बाल्टी को दबाएगी और फिर एक भरने की तलाश करेगी उनके बगल में बाल्टी? क्या एक बड़ी प्रारंभिक क्षमता प्रदर्शन में वृद्धि होगी?

इसके अलावा, यदि इसके लिए हैशपैप की तुलना में बेहतर डेटास्ट्रक्चर है, तो मैं इसके साथ पूरी तरह से खुला हूं।

+0

मानचित्र में कितनी प्रविष्टियां हैं, और स्ट्रिंग कुंजी की औसत लंबाई क्या है? – Avi

+1

कुल प्रविष्टियां 20 से 50 के बीच होगी और स्ट्रिंग की लंबाई की लंबाई 10-30 –

+1

के बीच एक चरित्र गणना होगी, यह अपेक्षाकृत छोटा है, क्या आप वाकई इसके बारे में चिंता करने की ज़रूरत है? जब तक आपके पास बहुत सारे उदाहरण न हों तो डिफ़ॉल्ट हैश मैप पैरामीटर के साथ जाएं। – starblue

उत्तर

13

अपने डेटा के लिए एक आदर्श हैशिंग समारोह के अभाव में, और यह सोचते हैं कि यह वास्तव में कुछ की एक सूक्ष्म अनुकूलन कि वास्तव में कोई फर्क नहीं पड़ता नहीं है, मैं कोशिश करेंगे निम्नलिखित:

डिफ़ॉल्ट लोड मान लें हैश मैप द्वारा उपयोग की जाने वाली क्षमता (.75) ज्यादातर स्थितियों में एक अच्छा मूल्य है। यह मामला है, आप इसका उपयोग कर सकते हैं, और अपने हैशैप की प्रारंभिक क्षमता को अपने स्वयं के ज्ञान के आधार पर सेट कर सकते हैं कि यह कितनी चीजें रखेगा - इसे सेट करें ताकि आरंभिक क्षमता x .75 = आइटमों की संख्या (राउंड अप) हो।

यदि यह एक बड़ा मानचित्र था, तो ऐसी स्थिति में जहां हाई स्पीड लुकअप वास्तव में महत्वपूर्ण था, मैं हैश मैप के बजाय trie के किसी प्रकार का उपयोग करने का सुझाव दूंगा। लंबे तारों के लिए, बड़े मानचित्रों में, आप एक और स्ट्रिंग-उन्मुख डेटा संरचना, जैसे कि त्रिभुज का उपयोग कर अंतरिक्ष, और कुछ समय बचा सकते हैं।

1

प्रविष्टियां बाल्टी को यादृच्छिक तरीके से आवंटित की जाती हैं। तो यदि आप प्रविष्टियों के रूप में कई बाल्टी भी करते हैं, तो कुछ बाल्टी में टकराव होंगे।

यदि आपके पास अधिक बाल्टी हैं, तो आपके पास कम टक्कर होगी। हालांकि, अधिक बाल्टी का मतलब स्मृति में फैल रहा है और इसलिए धीमा है। आम तौर पर 0.7-0.8 की सीमा में एक लोड कारक लगभग इष्टतम है, इसलिए शायद यह बदलने योग्य नहीं है।

हमेशा की तरह, यह संभवतः इन चीजों को microtuning पर लटका पाने से पहले प्रोफाइलिंग लायक है।

+0

में 'ज्ञान प्राप्त' जोड़ने के लिए भूल गए हैं "अधिक बाल्टी का मतलब स्मृति में फैल रहा है और इसलिए धीमा"। जब तक आप नैनो-अनुकूलन के बारे में बात नहीं कर रहे हैं, मुझे पूरा यकीन है कि यह बहुत गलत है। संबंधित हैश गणना (निरंतर समय) करके एक कुंजी को देखा जाता है, फिर बाल्टी खोजने के लिए एक मॉड्यूलो, फिर बाल्टी की सामग्री के माध्यम से फिर से अनुरोध किया जाता है जब तक अनुरोधित कुंजी बराबर() संग्रहीत नहीं होती है। इतना बड़ा तेज़ है (सबसे विचित्र हैशिंग स्थितियों में से सभी में)। आधुनिक सिस्टम में – Stephen

+0

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

+0

@ टॉमहॉविन-tackline: मैं तुम्हारा मुद्दा नहीं मिलता। यदि बाल्टी की संख्या तत्वों की संख्या के बराबर है, तो आपने कहा "स्मृति में फैल रहा है"। यदि आप कम बाल्टी का उपयोग करते हैं तो प्रत्येक बाल्टी को कई तत्व रखना होगा। किसी भी तरह से स्मृति एक ही सही रहता है? – Ashwin

2

मान लिया जाये कि (और यह एक खंड है) हैश फंक्शन पूर्णांक कुंजी

यह नहीं है की एक सरल आधुनिक 5 है। HashMap.java से:

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); 
} 

मैं भी नाटक करने के लिए मुझे लगता है कि समझ में नहीं जा रहा हूँ, लेकिन उस तरह सिर्फ इतना है कि स्थिति से निपटने के लिए बनाया गया है यह लग रहा है।

ध्यान दें कि बाल्टी की संख्या हमेशा 2 की शक्ति होती है, इससे कोई फर्क नहीं पड़ता कि आप किस आकार के लिए पूछते हैं।

+1

हैश पर धारणा इस तथ्य पर अनुमान लगाने के लिए थी कि टकराव होंगे, और डेटा का एक सही हैश प्राप्त करने का मौका शायद असंभव है। यहां तक ​​कि इस समारोह के साथ (जिसे मैं समझ में नहीं आता) मुझे लगता है कि एक अच्छा मौका है कि यह पूरी तरह से तारों को पार नहीं करेगा। आपके उत्तर के लिए धन्यवाद! –

3

मुझे सबसे अच्छा लगता है कि डिफ़ॉल्ट सेटिंग्स के साथ चारों ओर झुकाव न करें जब तक कि मुझे वास्तव में वास्तव में आवश्यकता न हो।

हॉटस्पॉट आपके लिए अनुकूलन करने का एक अच्छा काम करता है।

किसी भी मामले में; मैं पहले समस्या को मापने के लिए एक प्रोफाइलर (नेटबीन्स प्रोफाइलर कहें) का उपयोग करूंगा।

हम नियमित रूप से 10000 तत्वों के साथ नक्शे स्टोर करते हैं और यदि आपके पास एक अच्छा बराबर और हैशकोड कार्यान्वयन (और तार और इंटीग्रर्स करते हैं!) यह आपके द्वारा किए जा सकने वाले किसी भी लोड परिवर्तन से बेहतर होगा।

5

मान लीजिए कि आपका हैश फ़ंक्शन "अच्छा" है, सबसे अच्छी बात यह है कि प्रारंभिक आकार को तत्वों की अपेक्षित संख्या में सेट करना है, यह मानते हुए कि आप सस्ते अनुमान लगा सकते हैं। ऐसा करना एक अच्छा विचार है क्योंकि जब हैश मैप का आकार बदलता है तो उसे तालिका में प्रत्येक कुंजी के लिए हैश मानों को फिर से गणना करना होता है।

0.75 पर लोड कारक छोड़ दें। 0.75 का मान हैश लुकअप प्रदर्शन और प्राथमिक हैश सरणी के लिए अंतरिक्ष उपयोग के बीच एक अच्छा समझौता के रूप में अनुभवी रूप से चुना गया है। जैसे ही आप लोड फैक्टर को दबाते हैं, औसत लुकअप समय में काफी वृद्धि होगी।

यदि आप हैश टेबल व्यवहार के गणित में खोदना चाहते हैं: डोनाल्ड Knuth (1 99 8)। कंप्यूटर प्रोग्रामिंग की कला'। 3: छंटनी और खोज (द्वितीय संस्करण)। एडिसन-वेस्ले। पीपी 513-558। आईएसबीएन 0-201-89685-0।

+0

मुझे लगता है कि इस उत्तर के बारे में कुछ गलत है।यदि आप हैश मैप के आकार बदलने के बारे में बहुत चिंतित हैं, तो आपको शुरुआती क्षमता को तत्वों की अपेक्षित संख्या (जैसे 100) और लोड कारक को 0.75 पर सेट नहीं करना चाहिए, क्योंकि इसका मतलब है कि हैश मैप * किसी भी समय एक बार * आकार बदलता है (उदाहरण के लिए 75 वां तत्व)। यदि आप लोड कारक को 0.75 पर रखते हैं और हैश मैप को आकार बदलने से रोकना चाहते हैं, तो आपको प्रारंभिक क्षमता को '(अपेक्षित आकार/0.75) + 1' पर सेट करना होगा। – Arjan

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