2015-12-28 11 views
5

मान लें कि हमारे पास hashcode() फ़ंक्शन है, जिसका उपयोग दो ऑब्जेक्ट्स की समानता निर्धारित करने के लिए हमारे equals() विधि के अंदर किया जाएगा। क्या यह एक स्वीकृत/स्वीकार्य दृष्टिकोण है?क्या जावा में समानता निर्धारित करने के लिए हैशकोड का उपयोग करने की अनुशंसा की जाती है?

मान लें कि हम हैश कोड के सरल कार्यान्वयन का उपयोग करते हैं। (उदाहरण के लिए प्राइम नंबरों द्वारा गुणा किए गए कुछ इंस्टेंस चर।)

+0

हैशकोड की तुलना केवल एक चीज है जो आप वहां करने की योजना बना रहे हैं? या बस कई कदमों में से एक? – Thilo

+0

मैं इसका उपयोग करने की योजना नहीं बना रहा हूं, मैं सिर्फ इस विचार को फेंकना चाहता था क्योंकि यूनी में मेरे प्रशिक्षक ने बस "ऐसा नहीं किया" लेकिन क्यों समझाया नहीं जा सका। – k4kuz0

उत्तर

8

यह समानता की जांच करने का एक भयानक तरीका है, क्योंकि ऑब्जेक्ट्स को समान हैशकोड वापस करने के बराबर नहीं होना चाहिए।

आपको हमेशा इसके लिए बराबर विधि का उपयोग करना चाहिए।

सामान्य नियम है:

बराबरी विधि वस्तुओं ए और बी के लिए सच देता है, तो hashCode विधि ए और बी के लिए समान मान चाहिए।

इसका मतलब यह नहीं है कि यदि ए और बी के लिए हैशकोड विधि समान मान देता है, तो बराबर विधि को इन दो उदाहरणों के लिए सत्य वापस करना होगा।

उदाहरण के लिए

:

public int hashCode(){ 
    return 5; 
} 

एक मान्य है, हालांकि यह अक्षम, hashCode कार्यान्वयन हो।

संपादित करें:

public class Person{ 

private String name; 

public Person(String name){ this.name = name;} 

public String getName(){ return this.name;} 

@Override 
public boolean equals(Object o){ 
    if (!(o instanceof Person)){ return false;} 
    Person p = (Person)o; 
    boolean nameE = this.name == null ? p.getName() == null : this.name.equals(p.getName()); 
    boolean hashE = nameE ? true : randomTrueOrFalse(); 
    // the only moment you're sure hashE is true, is if the previous check returns true. 
    // in any other case, it doesn't matter whether they are equal or not, since the nameCheck returns false, so in best case, it's redundant 
    return nameE && hashE; 
} 

@Override 
public int hashCode(){ 
    int hash = generateValidHashCode(); 
    return hash; 
} 

} 
2

यह एक बहुत बुरा व्यवहार है:

के भीतर एक के बराबर होती है विधि कुछ इस तरह होगा इसका इस्तेमाल करने की। हैश को कम से कम टकराव माना जाता है, लेकिन आमतौर पर आपके पास संभव हैश की मात्रा की तुलना में वस्तुओं के लिए अधिक संभावनाएं होती हैं और कबूतर सिद्धांत के कारण कुछ विशिष्ट वस्तुओं में एक ही हैश होना चाहिए।

हैश की तुलना करते समय, आपके पास "झूठी सकारात्मक" होने का एक निश्चित मौका है।

0

इस

करते हैं यह है कि आप जोड़े में बराबर() और hashCode() ओवरराइड करने के लिए की जरूरत है, होने ही हैश ही मान होने के समान नहीं है सही है मत करो।

वास्तव में समानता की बात सोचने में कुछ प्रयास करें। यहां शॉर्टकट न करें यह आपको बाद में काट देगा।

1

वास्तव में, यह एक बुरा विचार नहीं है!

लेकिन सुनिश्चित करें कि आप असमानता निर्धारित करने के लिए इस विधि का उपयोग करते हैं, समानता नहीं। हैशिंग कोड समानता की जांच करने से तेज़ हो सकता है, खासकर जब हैशकोड संग्रहीत किया जाता है (उदाहरण के लिए java.lang.String में)।

दो वस्तु अलग hashcodes है, तो वे होना चाहिए अलग है, और वे एक ही हो सकता है।उदाहरण के लिए आप निम्नलिखित

Object a, b; 
if(a.hashCode() == b.hashCode()){ 
    if(a.equals(b)) return true; 
} 

return false; 

के रूप में इस विधि का उपयोग कर सकते हैं के बारे में पता कुछ मामलों में ऊपर कोड केवल equals() का उपयोग कर की तुलना में धीमी हो सकता है कि हो सकता है, खासकर जब ज्यादातर मामलों में a बराबर b करता है।

Object.java के प्रलेखन से:

  • दो तो वस्तुओं equals(Object) विधि के अनुसार बराबर हैं, तो बुला दो वस्तुओं में से प्रत्येक पर hashCode विधि एक ही पूर्णांक परिणाम का उत्पादन होगा।
  • यह आवश्यक नहीं है कि equals(java.lang.Object) विधि के अनुसार दो वस्तुएं असमान हों, फिर दो वस्तुओं में से प्रत्येक पर hashCode विधि को कॉल करने से अलग पूर्णांक परिणाम उत्पन्न हो जाएं। हालांकि, प्रोग्रामर को पता होना चाहिए कि असमान वस्तुओं के लिए अलग पूर्णांक परिणाम उत्पन्न करना हैशटेबल्स के प्रदर्शन में सुधार कर सकता है।
+0

यदि आप हैशकोड कैश कर रहे हैं तो यह एक अच्छा अनुकूलन है। अन्यथा, हैशकोड की गणना करना संभवतः उन सभी क्षेत्रों की तुलना करने से धीमा है जो इसमें जाते हैं। – Thilo

+0

चूंकि इससे झूठी सकारात्मक हो सकती है, इसलिए मैं इसे वास्तव में "बुरा विचार नहीं" कहूंगा। यह केवल तभी वैध होगा यदि आप इसे अतिरिक्त चेक के रूप में जोड़ते हैं, लेकिन फिर मूल रूप से आप जो कर रहे हैं वह है: यदि (allIsTrue && (allIsTrue || somethingSimilar)) तो मूल रूप से: allIsTrue ने पहले ही प्रश्न का उत्तर दिया है – Stultuske

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

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