"पर / बंद विषय" के ग्रे क्षेत्र में हो रही है, लेकिन ऑस्कर रेयेस के सुझाव के बारे में भ्रम को खत्म करने के लिए आवश्यक है कि अधिक हैश टकराव एक अच्छी बात है क्योंकि यह हाशप में तत्वों की संख्या को कम करता है। मैं गलत समझ सकता हूं कि ऑस्कर क्या कह रहा है, लेकिन मैं केवल एक ही नहीं लगता: kdgregory, delfuego, Nash0, और मैं सभी को एक ही (गलत) समझ साझा करता हूं।
यदि मैं समझता हूं कि ऑस्कर उसी हैशकोड के साथ उसी वर्ग के बारे में क्या कह रहा है, तो वह प्रस्ताव दे रहा है कि किसी दिए गए हैशकोड के साथ केवल एक वर्ग का एक उदाहरण हैशपॉप में डाला जाएगा। उदाहरण के लिए, यदि मेरे पास 1 के हैशकोड के साथ SomeClass का एक उदाहरण है और 1 के हैशकोड के साथ SomeClass के दूसरे उदाहरण में, SomeClass का केवल एक उदाहरण डाला गया है।
Http://pastebin.com/f20af40b9 पर जावा पास्टेबिन उदाहरण से यह संकेत मिलता है कि उपरोक्त सही ढंग से संक्षेप में बताया गया है कि ऑस्कर का प्रस्ताव क्या है।
किसी भी समझ या गलतफहमी के बावजूद, क्या होता है एक ही वर्ग के विभिन्न उदाहरणों को केवल एक बार हैशपॉप में डाला नहीं जाता है यदि उनके पास एक ही हैशकोड है - तब तक नहीं जब तक कि यह निर्धारित नहीं किया जाता है कि चाबियाँ समान हैं या नहीं। हैशकोड अनुबंध के लिए आवश्यक है कि समान वस्तुओं में समान हैशकोड हो; हालाँकि, यह आवश्यक नहीं है कि असमान वस्तुओं में अलग-अलग हैशकोड हों (हालाँकि यह अन्य कारणों से वांछनीय हो सकता है) [1]।
Pastebin.com/f20af40b9 उदाहरण (जो ऑस्कर कम से कम दो बार संदर्भित करता है) अनुसरण करता है, लेकिन प्रिंटलाइन के बजाय JUnit मुखर का उपयोग करने के लिए थोड़ा संशोधित किया गया है। इस उदाहरण का उपयोग इस प्रस्ताव का समर्थन करने के लिए किया जाता है कि समान हैशकोड टकराव का कारण बनते हैं और जब कक्षाएं समान होती हैं तो केवल एक प्रविष्टि बनाई जाती है (जैसे, इस विशिष्ट मामले में केवल एक स्ट्रिंग):
@Test
public void shouldOverwriteWhenEqualAndHashcodeSame() {
String s = new String("ese");
String ese = new String("ese");
// same hash right?
assertEquals(s.hashCode(), ese.hashCode());
// same class
assertEquals(s.getClass(), ese.getClass());
// AND equal
assertTrue(s.equals(ese));
Map map = new HashMap();
map.put(s, 1);
map.put(ese, 2);
SomeClass some = new SomeClass();
// still same hash right?
assertEquals(s.hashCode(), ese.hashCode());
assertEquals(s.hashCode(), some.hashCode());
map.put(some, 3);
// what would we get?
assertEquals(2, map.size());
assertEquals(2, map.get("ese"));
assertEquals(3, map.get(some));
assertTrue(s.equals(ese) && s.equals("ese"));
}
class SomeClass {
public int hashCode() {
return 100727;
}
}
हालाँकि, हैशकोड पूरी कहानी नहीं है। पास्टबिन उदाहरण की उपेक्षा क्या तथ्य यह है कि दोनों समान हैं s
और ese
समान हैं: वे दोनों "स्ट्रिंग" हैं। इस प्रकार, कुंजी का उपयोग करके s
या ese
उसके "ese"
रूप में मानचित्र की सामग्री को सम्मिलित करना या प्राप्त करना सभी समान हैं s.equals(ese) && s.equals("ese")
।
एक दूसरा परीक्षण दर्शाता है कि यह निष्कर्ष निकालना गलत है कि एक ही वर्ग पर समान हैशकोड कारण है - जब परीक्षण एक में बुलाया जाता s -> 1
है ese -> 2
तो मूल्य -> अधिलेखित हो map.put(ese, 2)
जाता है। परीक्षण दो में, s
और ese
अभी भी एक ही हैशकोड (जैसा कि सत्यापित है assertEquals(s.hashCode(), ese.hashCode());
) और वे एक ही वर्ग हैं। हालांकि, s
और इस परीक्षण में उदाहरण ese
हैं MyString
, जावा String
उदाहरण नहीं - इस परीक्षण के लिए एकमात्र अंतर के बराबर प्रासंगिक होने के साथ: String s equals String ese
ऊपर एक परीक्षण में, जबकि MyStrings s does not equal MyString ese
परीक्षण दो में:
@Test
public void shouldInsertWhenNotEqualAndHashcodeSame() {
MyString s = new MyString("ese");
MyString ese = new MyString("ese");
// same hash right?
assertEquals(s.hashCode(), ese.hashCode());
// same class
assertEquals(s.getClass(), ese.getClass());
// BUT not equal
assertFalse(s.equals(ese));
Map map = new HashMap();
map.put(s, 1);
map.put(ese, 2);
SomeClass some = new SomeClass();
// still same hash right?
assertEquals(s.hashCode(), ese.hashCode());
assertEquals(s.hashCode(), some.hashCode());
map.put(some, 3);
// what would we get?
assertEquals(3, map.size());
assertEquals(1, map.get(s));
assertEquals(2, map.get(ese));
assertEquals(3, map.get(some));
}
/**
* NOTE: equals is not overridden so the default implementation is used
* which means objects are only equal if they're the same instance, whereas
* the actual Java String class compares the value of its contents.
*/
class MyString {
String i;
MyString(String i) {
this.i = i;
}
@Override
public int hashCode() {
return 100727;
}
}
बाद की एक टिप्पणी के आधार पर, ऑस्कर ने जो कुछ भी पहले कहा था उसे उलटा करने के लिए लगता है और बराबरी के महत्व को स्वीकार करता है। हालांकि, यह अभी भी धारणा है कि समान है जो मायने रखता है, न कि "एक ही वर्ग", अस्पष्ट है (मेरा जोर)
"वास्तव में नहीं। सूची केवल तभी बनाई गई है जब हैश समान है, लेकिन कुंजी अलग है। उदाहरण के लिए यदि कोई स्ट्रिंग हैशकोड 2345 और इंटीगर समान हैशकोड 2345 देता है, तो पूर्णांक सूची में डाला जाता है क्योंकि स्ट्रिंग। बराबर (पूर्णांक) गलत है। लेकिन यदि आपके पास एक ही वर्ग है (या कम से कम-असमान रिटर्न सही है) तो उसी प्रविष्टि का उपयोग किया जाता है। उदाहरण के लिए नया स्ट्रिंग ("एक") और `नया स्ट्रिंग (" एक ") का उपयोग किया जाता है। कुंजियाँ, एक ही प्रविष्टि का उपयोग करेंगी। वास्तव में यह पहली बार में हाशप का पूर्ण बिंदु है! अपने लिए देखें: pastebin.com/f20af40b9 - ऑस्कर रेयेस "
पहले की टिप्पणियों के अनुसार समान वर्ग और समान हैशकोड के महत्व को स्पष्ट रूप से संबोधित करते हैं, जिसमें बराबरी का कोई उल्लेख नहीं है:
"@delfuego: खुद के लिए देखें: pastebin.com/f20af40b9 तो, इस प्रश्न में उसी वर्ग का उपयोग किया जा रहा है (एक मिनट रुको, उसी कक्षा का उपयोग सही किया जा रहा है?) जिसका अर्थ है कि जब समान हैश का उपयोग किया जाता है? का उपयोग किया जाता है और प्रविष्टियों की "सूची" नहीं है। - ऑस्कर रेयेस "
या
"वास्तव में यह प्रदर्शन को बढ़ाएगा। अधिक टकराव हैशटेबल ईक में कम प्रविष्टियां eq। कम काम करने के लिए। हैश नहीं है (जो ठीक दिखता है) और न ही हैशटेबल (जो बहुत अच्छा काम करता है) मैं शर्त लगा सकता हूं कि यह ऑब्जेक्ट पर है। निर्माण जहां प्रदर्शन अपमानजनक है। - ऑस्कर रेयेस "
या
"@kdgregory: हाँ, लेकिन केवल अगर टक्कर अलग-अलग वर्गों के साथ होती है, तो एक ही कक्षा के लिए (जो मामला है) एक ही प्रविष्टि का उपयोग किया जाता है। - ऑस्कर रेयेस"
फिर, मैं गलत समझ सकता हूं कि ऑस्कर वास्तव में क्या कहना चाह रहा था। हालांकि, उनकी मूल टिप्पणियों ने पर्याप्त भ्रम पैदा कर दिया है कि यह कुछ स्पष्ट परीक्षणों के साथ सब कुछ स्पष्ट करने के लिए विवेकपूर्ण लगता है, इसलिए इसमें कोई संदेह नहीं है।
[१] - प्रभावी जावा से, जोशुआ बलोच द्वारा दूसरा संस्करण :
जब भी किसी एप्लिकेशन के निष्पादन के दौरान एक से अधिक बार एक ही ऑब्जेक्ट पर इसे लागू किया जाता है, तो हैशकोड विधि को लगातार एक ही पूर्णांक को वापस करना होगा, बशर्ते कि ऑब्जेक्ट पर समान एस तुलना में उपयोग की गई कोई भी जानकारी संशोधित न हो। इस पूर्णांक को एक अनुप्रयोग के एक निष्पादन से एक ही अनुप्रयोग के दूसरे निष्पादन के अनुरूप नहीं रहना चाहिए।
यदि दो वस्तुएँ समान s (Obj ect) विधि के अनुसार समान हैं, तो दो वस्तुओं में से प्रत्येक पर हैशकोड विधि को कॉल करके एक ही पूर्णांक परिणाम का उत्पादन करना होगा।
यह आवश्यक नहीं है कि यदि दो वस्तुएं समान s (ऑब्जेक्ट) विधि के अनुसार असमान हैं, तो दो वस्तुओं में से प्रत्येक पर हैशकोड विधि को कॉल करके अलग पूर्णांक परिणाम उत्पन्न करना होगा। हालांकि, प्रोग्रामर को यह पता होना चाहिए कि असमान वस्तुओं के लिए अलग पूर्णांक परिणाम बनाने से हैश तालिकाओं के प्रदर्शन में सुधार हो सकता है।