दिलचस्प पोस्ट
एक एकल कार्रवाई के साथ कई फाइलें डाउनलोड करें String.equals () एकाधिक स्थितियों के साथ (और परिणामस्वरूप एक क्रिया) ember.js + हैंडलर्स: बनाम आउटलेट बनाम आंशिक बनाम दृश्य बनाम नियंत्रण क्यों MySQL पूर्ण आउटर पर एक सिंटैक्स त्रुटि की रिपोर्ट करता है? C ++ और बूस्ट का उपयोग करके मिलीसेकंड में वर्तमान समय प्राप्त करें कोड केवल 0.0, 0.0 जीपीएस समन्वय करेगा, जबकि NullPointerException फेंकता है ExpandoObject के वास्तविक लाभ क्या हैं? कमांड प्रॉम्प्ट से एक एपीके फाइल स्थापित करें? एक ही नाम के कई छिपा नियंत्रण तत्वों के साथ HTML प्रपत्र स्टेटिक लाइब्रेरी और स्विफ्ट सुपर () उठाता है "टाइप एरर: प्रकार होना चाहिए, क्लासबोज नहीं" नए-स्टाइल वर्ग के लिए सीएसएस एकल या एकाधिक पंक्ति ऊर्ध्वाधर संरेखण सी # कंसोल अनुप्रयोग में ऑरेंज पाठ का रंग? वीबीए का प्रयोग करके सभी सबफ़ोल्डर्स के माध्यम से लूप मोंगोज़: अद्वितीय होने के लिए फ़ील्ड के संयोजन को कैसे परिभाषित करना है?

अपाचे कॉमन्स बराबर / हैशोड बिल्डर

मुझे पता करने के लिए उत्सुक हूँ, यहां लोग जो EqualsBuilder / HashCodeBuilder का उपयोग करने के बारे में सोचते हैं, equals / HashCodeBuilder को लागू करने के लिए? क्या यह अपनी खुद की लेखन से बेहतर अभ्यास होगा? क्या यह सीतनिद्रा में होना अच्छा खेलता है? आपकी क्या राय है?

Solutions Collecting From Web of "अपाचे कॉमन्स बराबर / हैशोड बिल्डर"

कॉमन्स / लैंग बिल्डर्स महान हैं और मैं बिना सापेक्ष निष्पादन ओवरहेड (बिना और बिना हाइबरनेट) के वर्षों तक उनका उपयोग कर रहा हूं। लेकिन जैसा कि एलन लिखते हैं, गुवा का रास्ता भी अच्छा है:

यहां नमूना बीन है:

 public class Bean{ private String name; private int length; private List<Bean> children; } 

कॉमन्स / लैंग के साथ कार्यान्वित किया गया ये बराबर () और हैशोड () है:

 @Override public int hashCode(){ return new HashCodeBuilder() .append(name) .append(length) .append(children) .toHashCode(); } @Override public boolean equals(final Object obj){ if(obj instanceof Bean){ final Bean other = (Bean) obj; return new EqualsBuilder() .append(name, other.name) .append(length, other.length) .append(children, other.children) .isEquals(); } else{ return false; } } 

और यहाँ पेआवा के साथ:

 @Override public int hashCode(){ return Objects.hashCode(name, length, children); } @Override public boolean equals(final Object obj){ if(obj instanceof Bean){ final Bean other = (Bean) obj; return Objects.equal(name, other.name) && length == other.length // special handling for primitives && Objects.equal(children, other.children); } else{ return false; } } 

जैसा कि आप देख सकते हैं कि गवा का संस्करण छोटा है और अनावश्यक सहायक ऑब्जेक्ट से बचा जाता है। बराबर के मामले में, यह मूल्यांकन के शॉर्ट सर्किट की अनुमति भी देता है यदि एक पहले Object.equal() कॉल को गलत ( Object.equal() : कॉमन्स / लैंग में ObjectUtils.equals(obj1, obj2) विधि है जो समान शब्दों के साथ हो सकती हैं ऊपर के रूप में शॉर्ट-सर्किटिंग की अनुमति देने के लिए EqualsBuilder बजाय उपयोग किया गया)

इसलिए: हाँ, कॉमन्स लैंग बिल्डर्स मैन्युअल रूप से निर्मित equals() और hashCode() तरीके (या उन भयानक राक्षस ग्रहण आपके लिए उत्पन्न होंगे) पर बहुत बेहतर हैं, लेकिन गवा संस्करण भी बेहतर हैं।

और हाइबरनेट के बारे में एक नोट:

अपने बराबर (), हैशोड () और टोस्ट्रिंग () कार्यान्वयन में आलसी संग्रह का उपयोग करने के बारे में सावधान रहें। यदि आपके पास एक खुले सत्र नहीं है, तो वह बुरी तरह असफल हो जायेगा।


नोट (बराबर के बारे में):

क) ऊपर के बराबर () के दोनों संस्करणों में, आप इनमें से एक या दोनों शॉर्टकट का उपयोग भी कर सकते हैं:

 @Override public boolean equals(final Object obj){ if(obj == this) return true; // test for reference equality if(obj == null) return false; // test for null // continue as above 

बी) बराबर () अनुबंध की अपनी व्याख्या के आधार पर, आप लाइन (एस) को भी बदल सकते हैं

  if(obj instanceof Bean){ 

सेवा मेरे

  // make sure you run a null check before this if(obj.getClass() == getClass()){ 

यदि आप दूसरे संस्करण का उपयोग करते हैं, तो आप शायद अपने equals() विधि के अंदर super(equals()) कॉल करना चाहते हैं। राय यहां भिन्न होती है, विषय इस प्रश्न में चर्चा की जाती है:

एक गुवा ऑब्जेक्ट्स। हाकोड () कार्यान्वयन में सुपरक्लास को शामिल करने का सही तरीका है?

(हालांकि यह hashCode() के बारे में है, वही equals() पर लागू होता है


नोट ( कयहर से टिप्पणी से प्रेरित)

Objects.hashCode(..) (जैसा कि अंतर्निहित Arrays.hashCode(...) ) खराब प्रदर्शन हो सकता है यदि आपके पास बहुत से आदिम फ़ील्ड हैं ऐसे मामलों में, EqualsBuilder वास्तव में बेहतर समाधान हो सकता है

दोस्तों, उठो! जावा 7 के बाद से मानक पुस्तकालय में बराबर और हैशोड के लिए सहायक विधियां हैं। उनका उपयोग अमरूद विधियों के उपयोग के लिए पूरी तरह से समतुल्य है।

यदि आप किसी तृतीय पक्ष लाइब्रेरी पर निर्भर नहीं रहना चाहते हैं (हो सकता है कि आप सीमित संसाधन वाले एक उपकरण को चला रहे हों) और आप भी अपनी खुद की विधियों को टाइप नहीं करना चाहते हैं, तो आप आईडीई को काम भी कर सकते हैं, उदा। ग्रहण उपयोग में

 Source -> Generate hashCode() and equals()... 

आपको 'मूल' कोड मिलेगा जो आप की तरह कॉन्फ़िगर कर सकते हैं और आपको परिवर्तनों पर समर्थन करना है।


उदाहरण (ग्रहण जूनो):

 import java.util.Arrays; import java.util.List; public class FooBar { public String string; public List<String> stringList; public String[] stringArray; /* (non-Javadoc) * @see java.lang.Object#hashCode() */ @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((string == null) ? 0 : string.hashCode()); result = prime * result + Arrays.hashCode(stringArray); result = prime * result + ((stringList == null) ? 0 : stringList.hashCode()); return result; } /* (non-Javadoc) * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; FooBar other = (FooBar) obj; if (string == null) { if (other.string != null) return false; } else if (!string.equals(other.string)) return false; if (!Arrays.equals(stringArray, other.stringArray)) return false; if (stringList == null) { if (other.stringList != null) return false; } else if (!stringList.equals(other.stringList)) return false; return true; } } 

इक्वलबिल्डर और हैशोडोडिल्डर के दो मुख्य पहलुओं को मैन्युअल रूप से लिखित कोड से अलग किया गया है:

  • अशक्त हैंडलिंग
  • उदाहरण सृजन

Equalsbuilder और HashCodeBuilder उन क्षेत्रों की तुलना करना आसान बनाते हैं जो शून्य हो सकते हैं। मैन्युअल रूप से लिखा कोड के साथ यह बहुत सारे बॉयलरप्लेट बनाता है

EqualsBuilder दूसरी तरफ एक उदाहरण बनाने के लिए विधि कॉल के बराबर होगा। अगर आपके बराबर तरीके कॉल करते हैं तो अक्सर यह बहुत सारे उदाहरण पैदा करेगा।

हाइबरनेट के लिए बराबर और हैश कोड कार्यान्वयन कोई फर्क नहीं पड़ता। वे सिर्फ एक कार्यान्वयन विवरण हैं। बिल्डर के रनटाइम ओवरहेड (यहां तक ​​कि एस्केप विश्लेषण के बिना) हाइबरनेट के साथ लोड किए गए लगभग सभी डोमेन ऑब्जेक्ट्स को अनदेखा किया जा सकता है डाटाबेस और संचार ओवरहेड महत्वपूर्ण होगा।

जैसा कि स्कैफ़मैन ने उल्लेख किया है कि प्रतिबिंब संस्करण का उपयोग उत्पादन कोड में नहीं किया जा सकता है। प्रतिबिंब धीमा हो जाएगा और सभी के लिए "कार्यान्वयन" सही नहीं होगा, लेकिन सबसे सरल वर्ग सभी सदस्यों को खाते में लेना भी खतरनाक है क्योंकि नव शुरू किए गए सदस्यों में विधि व्यवहार के बराबर परिवर्तन होता है। रिफ्लेक्शन संस्करण परीक्षण कोड में उपयोगी हो सकता है।

अगर आप अपना खुद का नहीं लिखना चाहते हैं, तो गूगल पेरू (पूर्व में Google संग्रह) का उपयोग करने की संभावना भी है

यदि आप बस इकाई सेम के साथ काम कर रहे हैं जहां आईडी प्राथमिक कुंजी है, तो आप सरल कर सकते हैं।

  @Override public boolean equals(Object other) { if (this == other) { return true; } if ((other == null) || (other.getClass() != this.getClass())) { return false; } EntityBean castOther = (EntityBean) other; return new EqualsBuilder().append(this.getId(), castOther.getId()).isEquals(); } 

मेरी राय में यह हाइबरनेट के साथ अच्छी तरह से नहीं खेलता है, खासकर उदाहरण के उदाहरणों की तुलना में लंबाई, नाम और कुछ इकाई के लिए बच्चों की तुलना। सीतनिद्रा में होना बराबर () और हैशोड () में उपयोग की जाने वाली व्यावसायिक कुंजी का उपयोग करने की सलाह देती है , और उनके पास उनके कारण हैं यदि आप अपनी व्यावसायिक कुंजी पर ऑटो बराबर () और हैशोड () जनरेटर का उपयोग करते हैं, तो ठीक है, प्रदर्शन समस्याओं को पहले भी उल्लेख किया जाना चाहिए। लेकिन आम तौर पर लोग सभी गुणों का उपयोग करते हैं जो IMO बहुत गलत हैं उदाहरण के लिए, मैं वर्तमान में परियोजना पर काम कर रहा हूं जहां संस्थाएं पाओमैमेट के साथ @ऑटोपॉर्फ़टी के साथ लिखी गई हैं, जो मैं वास्तव में खराब पैटर्न पर विचार करता हूं

हैश कोड () और बराबर () का उपयोग करने के लिए उनके दो मुख्य परिदृश्य हैं:

  • जब आप एक सेट में लगातार कक्षाएं (कई मूल्यवान संगठनों का प्रतिनिधित्व करने का सुझाव दिया गया) और
  • जब आप अलग-अलग उदाहरणों का पुनः उपयोग करते हैं

तो मान लें कि हमारी संस्था इस तरह दिखती है:

 class Entity { protected Long id; protected String someProp; public Entity(Long id, String someProp); } Entity entity1 = new Entity(1, "a"); Entity entity2 = new Entity(1, "b"); 

दोनों हाइबरनेट के लिए एक ही इकाई हैं, जो कुछ समय से कुछ सत्र से प्राप्त किए गए हैं (उनके आईडी और वर्ग / तालिका समान हैं)। लेकिन जब हम सभी सममूल्य पर एक हैश कोड () ऑटो के बराबर लागू करते हैं, तो हमारे पास क्या है?

  1. जब आप इकाई 2 को लगातार सेट में डालते हैं जहां इकाई 1 पहले से मौजूद है, तो इसे दो बार रखा जाएगा और प्रतिबद्ध के दौरान अपवाद का परिणाम होगा।
  2. यदि आप पृथक इकाई 2 को सत्र में संलग्न करना चाहते हैं, जहां इकाई 1 पहले से ही मौजूद है (शायद, मैंने इसे विशेष रूप से परीक्षण नहीं किया है) ठीक से मर्ज नहीं किया जाएगा।

इसलिए, 99% प्रोजेक्ट के लिए मैं, आधार इकाई वर्ग में एक बार लिखे गए बराबर () और हैशकोड () के निम्न कार्यान्वयन का उपयोग करता हूं, जो हाइबरनेट अवधारणाओं के अनुरूप है:

 @Override public boolean equals(Object obj) { if (StringUtils.isEmpty(id)) return super.equals(obj); return getClass().isInstance(obj) && id.equals(((IDomain) obj).getId()); } @Override public int hashCode() { return StringUtils.isEmpty(id) ? super.hashCode() : String.format("%s/%s", getClass().getSimpleName(), getId()).hashCode(); } 

क्षणिक इकाई के लिए मैं उसी तरह से करता हूं जो सीतनिद्रा में होना दृढ़ता से कदम, अर्थात्। मैं उदाहरण मिलान का उपयोग करता हूं लगातार वस्तुओं के लिए मैं अद्वितीय कुंजी की तुलना करता हूँ, जो कि तालिका / आईडी है (मैं कभी कंपोजिट कुंजियों का उपयोग नहीं करता)।

बस के मामले में, दूसरों को यह उपयोगी मिलेगा, मैं हैश कोड गणना के लिए इस हेल्पर क्लास के साथ आया हूं जो उपरोक्त वर्णित अतिरिक्त ऑब्जेक्ट निर्माण ओवरहेड से बचा जाता है (वास्तव में, ऑब्जेक्ट्स ओवरशिप। विरासत के रूप में यह प्रत्येक स्तर पर एक नई सरणी पैदा करेगा!)

उपयोग का उदाहरण:

 public int hashCode() { return HashCode.hash(HashCode.hash(timestampMillis), name, dateOfBirth); // timestampMillis is long } public int hashCode() { return HashCode.hash(super.hashCode(), occupation, children); } 

हैशकोल्ड सहायक:

 public class HashCode { public static int hash(Object o1, Object o2) { return add(Objects.hashCode(o1), o2); } public static int hash(Object o1, Object o2, Object o3) { return hash(Objects.hashCode(o1), o2, o3); } ... public static int hash(Object o1, Object o2, ..., Object o10) { return hash(Objects.hashCode(o1), o2, o3, ..., o10); } public static int hash(int initial, Object o1, Object o2) { return add(add(initial, o1), o2); } ... public static int hash(int initial, Object o1, Object o2, ... Object o10) { return add(... add(add(add(initial, o1), o2), o3) ..., o10); } public static int hash(long value) { return (int) (value ^ (value >>> 32)); } public static int hash(int initial, long value) { return add(initial, hash(value)); } private static int add(int accumulator, Object o) { return 31 * accumulator + Objects.hashCode(o); } } 

मैंने सोचा है कि 10 डोमेन मॉडल में अधिकतम उचित गुणों की संख्या है, यदि आपके पास अधिक है तो आपको स्ट्रिंग्स और प्रीमिटीव्स के ढेर को बनाए रखने के बजाय अधिक श्रेणी को पुनर्संरचना और शुरू करने का विचार करना चाहिए।

कमियां हैं: यदि आपके पास प्राइमटाइव्स और / या एरेज़ हैं जो आपको गहराई से हैश करने की आवश्यकता है तो यह उपयोगी नहीं है। (आम तौर पर यह मामला है जब आपको फ्लैट (स्थानांतरण) वस्तुओं से निपटना पड़ता है जो आपके नियंत्रण से बाहर है)।