2016-03-09 11 views
7

मुझे हाल ही में पता चला है कि जावा 8 हैश मानचित्र लिंक किए गए सूची के बजाय बाइनरी पेड़ का उपयोग करते हैं और हैश कोड ब्रांचिंग कारक के रूप में उपयोग किया जाता है। मैं समझता हूं कि उच्च टकराव के मामले में लुकअप ओ से ओ (लॉग एन) तक कम हो जाता है (एन) बाइनरी पेड़ों का उपयोग करके। मेरा सवाल यह है कि वास्तव में यह अच्छा करता है क्योंकि अमूर्त समय जटिलता अभी भी ओ (1) है और शायद यदि आप सभी बाल्टी में सभी प्रविष्टियों को सभी के लिए एक ही हैश कोड प्रदान करके मजबूर करना चाहते हैं चाबियाँ हम एक महत्वपूर्ण समय अंतर देख सकते हैं लेकिन उनके सही दिमाग में कोई भी ऐसा नहीं करेगा।जावा 8 में हैश नक्शा लिंक किए गए सूची के बजाय बाइनरी पेड़ का उपयोग क्यों करते हैं?

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

+2

यह बहस नहीं है। मैं उद्धरण दे रहा हूं: * मेरा सवाल यह है कि यह वास्तव में क्या करता है [...] शायद अगर आप [...] हम एक महत्वपूर्ण समय अंतर देख सकते हैं लेकिन उनके सही दिमाग में कोई भी ऐसा नहीं करेगा। *। तो आप कह रहे हैं कि इसे किसी भी मामले को संभालने के लिए डिज़ाइन किया गया था, जो उनके सही दिमाग में नहीं होगा, इसलिए देवताओं ** स्पष्ट रूप से ** एक गूंगा मामला संभाला है, इसलिए देवता गूंगा हैं और आप सत्य धारण करते हैं। मैं आपके प्रश्न को दोबारा लिखने का सुझाव देता हूं। – Tunaki

+1

आपका प्रश्न कोई समझ नहीं आता है। यदि आप मानते हैं कि हैश टकराव नहीं होगा, तो बाइनरी पेड़ * अधिक * उपभोग नहीं करेगा क्योंकि बाइनरी पेड़ का उपयोग तब किया जाएगा जब * हैश टकराव हो। अधिक सटीक होने के लिए, लिंक किए गए सूची से बाइनरी पेड़ में कार्यान्वयन स्विच से पहले टकराव की संख्या को सीमा से अधिक होना चाहिए। – Holger

+0

@ टुनकी मैं विशेष रूप से लोगों को जानबूझकर उस परिदृश्य को लाभ दिखाने के लिए कोशिश कर रहा था और अगर मैंने सोचा कि इसमें कुछ और नहीं है तो मैंने कभी इसे एक प्रश्न के रूप में नहीं पूछा होगा। – user1613360

उत्तर

15

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

अधिक जानकारी के लिए JEP-180 देखें।

+0

सहमत हैं लेकिन उपयोगकर्ता अंतर्निहित हैश फ़ंक्शन को जानने के बिना टकराव बढ़ाने के लिए इनपुट कैसे तैयार कर सकता है? – user1613360

+2

@ user1613360, 'स्ट्रिंग' के लिए हैश फ़ंक्शन प्रसिद्ध है और [दस्तावेज] (https://docs.oracle.com/javase/8/docs/api/java/lang/String.html#hashCode--), तो यह एक बड़ी समस्या नहीं है। प्रत्येक जावा कार्यान्वयन को एक ही फ़ंक्शन का उपयोग करना चाहिए। –

+2

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

8

आपके प्रश्न में कुछ गलत परिसर शामिल हैं।

  1. एक बाल्टी टक्कर जरूरी एक हैश टकराव नहीं है। एक ही बाल्टी पर समाप्त होने के लिए आपको दो ऑब्जेक्ट्स के लिए एक ही हैश कोड रखने की आवश्यकता नहीं है। बाल्टी एक सरणी का एक तत्व है और हैश कोड को किसी विशेष अनुक्रमणिका में मैप किया जाना है। चूंकि सरणी आकार Map के आकार के संबंध में उचित होना चाहिए, इसलिए आप बाल्टी टकराव से बचने के लिए मनमाने ढंग से सरणी आकार नहीं बढ़ा सकते हैं। यहां तक ​​कि सैद्धांतिक सीमा भी है कि एक सरणी आकार अधिकतम 2³¹ पर हो सकता है जबकि 2 ² संभव हैश कोड हैं।
  2. हैश टकराव होने से खराब प्रोग्रामिंग का संकेत नहीं है। 2 वर्ग मीटर से अधिक मूल्य स्थान वाले सभी ऑब्जेक्ट्स के लिए, एक ही हैश कोड वाले विशिष्ट ऑब्जेक्ट्स की संभावना अपरिहार्य है। String एस एक स्पष्ट उदाहरण हैं, लेकिन Point भीमूल्यों या एक सादा Long कुंजी के साथ अपरिहार्य हैश टकराव हैं। इसलिए वे आपके विचार से अधिक आम हो सकते हैं और यह उपयोग के मामले पर भारी निर्भर करता है।
  3. कार्यान्वयन केवल बाइनरी पेड़ पर स्विच करता है जब बाल्टी में टकराव की संख्या एक निश्चित दहलीज से अधिक हो जाती है ताकि उच्च स्मृति लागत केवल तभी लागू हो जब वे भुगतान करेंगे। ऐसा लगता है कि वे कैसे काम करते हैं, इस बारे में एक आम गलतफहमी प्रतीत होती है। चूंकि बाल्टी टक्कर जरूरी हैश टकराव नहीं है, बाइनरी खोज पहले हैश कोड खोजेगी। केवल जब हैश कोड समान हैं और कुंजी उचित रूप से Comparable लागू करती है, तो इसका प्राकृतिक क्रम उपयोग किया जाएगा। वेब पर पाए गए उदाहरण जानबूझकर Comparable कार्यान्वयन के उपयोग को प्रदर्शित करने के लिए ऑब्जेक्ट्स के लिए एक ही हैश कोड का उपयोग करते हैं जो अन्यथा दिखाई नहीं देगा। वे जो ट्रिगर करते हैं वह केवल कार्यान्वयन का अंतिम उपाय है।
  4. Tagir pointed out के रूप में, यह समस्या किसी सॉफ़्टवेयर की सुरक्षा को प्रभावित कर सकती है क्योंकि धीमी गति से गिरावट के कारण डीओएस हमलों की संभावना खुल सकती है। इस मुद्दे को हल करने के लिए पिछले जेआरई संस्करणों में कई प्रयास हुए हैं जिनके बाइनरी पेड़ की स्मृति खपत की तुलना में अधिक कमी आई है। उदाहरण के लिए, जावा 7 में एरे प्रविष्टियों के लिए हैश कोड के मैपिंग को यादृच्छिक करने का प्रयास किया गया था, जिसने this bug report में दस्तावेज के रूप में प्रारंभिक ओवरहेड का कारण बना दिया था। यह इस नए कार्यान्वयन के मामले में नहीं है।
+0

संबंधित: [http://www.javaspecialists.eu /archive/Issue235.html ](http://www.javaspecialists.eu/archive/Issue235.html) –

+0

यह बताते हुए कि "बाल्टी टकराव" जरूरी नहीं है कि "हैश टक्कर" यहां महत्वपूर्ण है। कई प्रोग्रामर गलती से सोचते हैं कि वे समानार्थी हैं। – nanosoft

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