1. Why Hashcode ()؟
العناصر الموجودة في المجموعة غير مضطربة وغير قابلة للتكرار ، فما هو الأساس للحكم على ما إذا كان تكرار عنصرين؟ وقالت قرد معين: "بالطبع ، يتم استخدام Object.equal () لمقارنة ما إذا كانت الكائنات متساوية". ومع ذلك ، هناك عدد كبير من الكائنات في المجموعة ، وسيزيد عدد مقارنات عناصر الكائنات المضافة إلى المجموعة تدريجياً ، مما يقلل بشكل كبير من كفاءة عملية البرنامج. تستخدم Java خوارزمية التجزئة (تسمى أيضًا خوارزمية التجزئة) لحل هذه المشكلة. يتم تعيين الكائن (أو البيانات) مباشرة إلى عنوان وفقًا لخوارزمية معينة ، ويتم تحسين كفاءة الوصول إلى الكائن بشكل كبير. وبهذه الطريقة ، عندما تحتاج مجموعة تحتوي على عدد كبير من العناصر إلى إضافة عنصر (كائن) ، اتصل أولاً بـ HashCode () لهذا العنصر ، ويمكنك وضع موقع التخزين الفعلي لهذا العنصر في وقت واحد. إذا لم يكن هناك عنصر في هذا الموضع ، فهذا يعني أنه يتم تخزين الكائن في المجموعة المحددة لأول مرة ، ويتم تخزين الكائن مباشرة في هذا الموضع ؛ إذا كان هناك كائن في هذا الموضع ، اتصل بـ equal () لمعرفة ما إذا كان الكائنان متساويان. إذا كان الشيء نفسه صحيحًا ، فتجاهل العنصر ولم يكن موجودًا. إذا لم يكن متساوًا ، فهو تجزئة للعناوين الأخرى.
2. كيف تستخدم hashcode ()؟
تحتوي لغة Java على خمسة متطلبات يجب اتباعها من أجل Equal () في تصميم APE.
التماثل. إذا كان A.equal (B) يعيد "True" ، فيجب أن يعود B.equal (A) أيضًا "True".
عاكس. أ.
متعدية. إذا كان A.equal (B) يعيد "True" و B.equal (C) إرجاع "True" ، فيجب أن يعود C.equal (A) "True".
تناسق. إذا كان A.equal (ب) يعيد "صحيح" ، طالما أن محتوى A و B يظل دون تغيير ، بغض النظر عن عدد المرات التي يجب أن تعود فيها A.equal (ب) "صحيح".
في أي حال ، يعيد A.equals (NULL) دائمًا "خطأ" ؛ أ.
العلاقة بين قيمة إرجاع HashCode () و equals ().
إذا كان A.equals (B) يعيد "True" ، فيجب أن يكون Hashcode () من A و B متساويًا.
إذا كان A.equals (ب) يعيد "false" ، فقد يكون hashcode () من A و B متساويين أو قد يكون غير متكافئ.
هنا مثال. في تطوير البرمجيات الفعلية ، من الأفضل إعادة كتابة هاتين الطريقتين.
موظف الطبقة العامة {int amployeeId ؛ اسم السلسلة // ستكون الأساليب الأخرى موجودة هنا @Override Public Boolean (Object OBJ) {if (obj == this) return true ؛ الموظف EMP = (الموظف) OBJ ؛ if (experieseID.equals (emp.getemployeID ()) && name == emp.getName ()) return true ؛ العودة كاذبة } Override public int hashcode () {int hash = 1 ؛ التجزئة = التجزئة * 17 + الموظف ؛ hash = hash * 31 + name.hashCode () ؛ عودة التجزئة. }}3. ما يلي هو التركيز على طريقة تنفيذ HashCode () للفئات الشائعة الاستخدام.
hascode () من فئة السلسلة
public int hashcode () {int h = hash ؛ if (h == 0) {int Off = Offset ؛ char val [] = value ؛ int len = count ؛ لـ (int i = 0 ؛ i <len ؛ i ++) {h = 31*h+val [Off ++] ؛ } التجزئة = H ؛ } إرجاع H ؛ }الشيء الأكثر إثارة للاهتمام في هذا الرمز هو طريقة تنفيذ التجزئة. قيمة التجزئة المحسوبة النهائية هي:
S [0] 31N-1 + S [1] 31N-2 + ... + S [N-1]
S [i] هو الحرف i-th لسلسلة ، و n هو طول السلسلة. إذن لماذا تستخدم 31 هنا بدلاً من الأرقام الأخرى؟
31 هو رقم رئيسي غريب. إذا كان المضاعف هو رقم زوجي ويخفق الضرب ، فستفقد المعلومات لأن الضرب مع 2 يعادل تشغيل التشغيل. فوائد استخدام الأرقام الأولية ليست واضحة ، ولكن يتم استخدام نتائج التجزئة تقليديًا لحساب نتائج التجزئة. 31 لها ميزة جيدة ، وهي استخدام التحول والطرح بدلاً من الضرب للحصول على أداء أفضل: 31*i == (i << 5) -i. يمكن لـ VMs إكمال هذا التحسين تلقائيًا. (من جافا الفعالة)
hascode () من فئة الكائن
HashCode () هي طريقة أصلية في فئة الكائن. كيف تسمي الأساليب الأصلية؟
Hashcode الأصلي العام () ؛
يمكن العثور على فئة الطريقة الأصلية لفئة الكائن هنا. يرجى قراءة مدونة أخرى للتحليل المتعمق
أساليب jninativemethod ثابتة [] = {{"hashcode" ، "() i" ، (void *) & jvm_ihashcode} ، {"wait" ، "(j) v" ، (void *) & jvm_monitorwait} ، {" "() v" ، (void *) & jvm_monitornotifyall} ، {"clone" ، "() ljava/lang/object ؛" ، (void *) & jvm_clone} ،} ؛يتضمن الكود المصدر getClass () (انظر السطر 58) ، إلخ. يتم تعريف HashCode () (انظر السطر 43) كمؤشر إلى JVM_IhashCode.
تحدد JVM.CPP وظيفة JVM_IHASHCODE (السطر 504). تستدعي هذه الوظيفة ObjectSynchronizer :: fastthashcode ، والتي يتم تحديدها في synchronizer.cpp. لتنفيذ FashashCode في السطر 576 و get_next_hash في السطر 530 ، يمكنك الرجوع إلى تنفيذ FashashCode في السطر 576 و get_next_hash في السطر 530.