هذا سؤال كلاسيكي للغاية في جافا وغالبًا ما يتم طرحه خلال المقابلات. في الواقع ، ذكرت العديد من الكتب أو المقالات أنه يجب عليك زيادة تحميل Hashcode () و equals () لتحقيق البحث عن مفاتيح مخصصة في hashmap. ومع ذلك ، يبدو أن عدد قليل من المقالات تتحدث عن سبب حاجتك إلى القيام بذلك وما هي العواقب التي ستسببها عدم القيام بذلك ، لذلك سأكتب هذا المقال لشرح ذلك.
بادئ ذي بدء ، ماذا يحدث إذا استخدمنا فئة الشخص التالية مباشرة كمفتاح وتخزينها في HashMap؟
الشخص العام {private string id ؛ الشخص العام (معرف السلسلة) {this.id = id ؛ }} استيراد java.util.hashmap ؛ الفئة العامة الرئيسية {public static void main (string [] args) {hashmap <person ، string> map = new hashmap <person ، string> () ؛ map.put (شخص جديد ("001") ، "نتائج") ؛ map.put (شخص جديد ("002") ، "Linyin") ؛ map.put (شخص جديد ("003") ، "هنريلين") ؛ map.put (شخص جديد ("003") ، "نتائج") ؛ System.out.println (map.toString ()) ؛ System.out.println (map.get (شخص جديد ("001"))) ؛ System.out.println (map.get (شخص جديد ("002"))) ؛ System.out.println (map.get (شخص جديد ("003"))) ؛ }}إذن ما هي نتيجة الإخراج؟
{person@6e4d4d5e = henrylin ، person@275cea3 = النتائج ، شخص@15128ee5 = النتائج ، الشخص@4513098 = linyin} nullnullnullيمكننا أن نرى أن هناك مشكلتان هنا:
1. أثناء عملية الإضافة ، أضفنا زوج القيمة المفتاح من المفتاح = الشخص الجديد ("003") مرتين. في التوقع ، يجب أن يكون هناك واحد فقط من هذه الزوجات القيمة الرئيسية في HashMap. لأن المفتاح (المتوقع) هو نفسه ، لا ينبغي إضافته بشكل متكرر. يجب أن تحل Value = "FindingSeaLy" إلى أن المرة الثانية يجب أن تحل محل القيمة الأصلية = "Henrylin". ولكن في المدخلات ، وجدنا أن الموقف المتوقع لم يحدث ، ولكن هناك اثنين من أزواج القيمة الرئيسية من القيمة = "النتائج" و Value = "Henrylin" في hashmap ، ولا تزال قيمهما الرئيسية مختلفة ، وهو أمر خاطئ بشكل واضح.
2. عند الحصول على قيمة القيمة ، نستخدم كائنات ثلاثة شخص للبحث. هذه الكائنات الثلاثة هي نفس القيم الرئيسية الثلاثة التي قمنا بتخزينها للتو (في التوقع) ، لكن البحث هو ثلاث قيم خالية ، وهو أمر خاطئ أيضًا.
لذلك ، تم وصف الطريقة الصحيحة بالفعل في العديد من الأماكن. يتم تعديل فئة الشخص مباشرة ، وسائل المساواة والهزلة الزائدة ، والفئة المعدلة على النحو التالي:
الشخص العام {private string id ؛ الشخص العام (معرف السلسلة) {this.id = id ؛ } Override Public Boolean يساوي (كائن O) {if (this == o) إرجاع true ؛ if (o == null || getClass ()! = o.getClass ()) return false ؛ شخص الشخص = (شخص) o ؛ if (id! = null؟! id.equals (person.id): person.id! = null) return false ؛ العودة صحيح. } Override public int hashcode () {return id! = null؟ id.HashCode (): 0 ؛ }}ثم ، عندما نعيد تنفيذ إجراء التفتيش أعلاه ، تكون النتائج كما يلي:
{person@ba31 = النتائج ، person@ba32 = linyin ، person@ba33 = foundingingealy} foundingealinyinfindingsealyكما يمكن أن نرى ، تم تصحيح جميع النقاط البارزة والأخطاء التي تم الإشارة إليها. فلماذا يحدث هذا؟
في Hashmap ، ترتيب مقارنة مفاتيح البحث هو:
1. احسب رمز التجزئة للكائن لمعرفة ما إذا كان موجودًا في الجدول.
2. تحقق مما إذا كان الكائن الموجود في موقع رمز التجزئة المقابل يساوي الكائن الحالي.
من الواضح أن الخطوة الأولى هي استخدام طريقة hashcode () ، والخطوة الثانية هي استخدام طريقة متساوية (). عند عدم إجراء أي تحميل زائد ، سيتم استدعاء هاتين الطريقتين من فئة الكائن افتراضيًا في هاتين الخطوتين. في الكائن ، يتم حساب طريقة حساب رمز التجزئة بناءً على عنوان الكائن. تختلف عناوين الكائن للشخصين ("003") ، وبالتالي فإن رمز التجزئة الخاص بهما مختلفان أيضًا. بطبيعة الحال ، لن يعاملهم HashMap على نفس المفتاح. في الوقت نفسه ، في الافتراضي يساوي () الكائن ، تتم مقارنته أيضًا بناءً على عنوان الكائن. بطبيعة الحال ، شخص واحد ("003") وشخص آخر ("003") ليسوا متساوين.
بعد فهم ذلك ، من السهل معرفة سبب حاجتك إلى زيادة تحميل كل من Hashcode () والطرق المساواة.
• الحمولة الزائدة hashcode () هو الحصول على نفس رمز التجزئة لنفس المفتاح ، بحيث يمكن وضع hashmap على المفتاح الذي حددناه.
• التحميل الزائد متساوي () هو إظهار hashmap أن الكائن الحالي والكائن المحفوظ على المفتاح متساوين ، بحيث يمكننا حقًا الحصول على زوج القيمة الرئيسية المقابلة للمفتاح.
هناك تفاصيل أخرى. في فئة الشخص ، التركيز على طريقة HashCode () هو:
Overridepublic int hashcode () {return id! = null؟ id.HashCode (): 0 ؛}النقطة التي قد تكون في حيرة هنا هي: لماذا يمكن استخدام رمز التجزئة لمتغير من سلسلة النوع كقيمة رمز التجزئة لفئة الشخص؟ هل رموز التجزئة للشخص الجديد (سلسلة جديدة ("003")) وشخص جديد (سلسلة جديدة ("003")) متساوية؟
لنلقي نظرة على إخراج الكود التالي:
system.out.println ("infertingsea" .hashCode ()) ؛ system.out.println ("inferendingea" .hashCode ()) ؛ system.out.println (سلسلة جديدة ("نتائج"). hashcode () ؛ system.out.println (جديد سلسلة ("نتائج"). hashcode ()) ؛ 728795174728795174728795174728795174يمكنك أن ترى أن مخرجات العبارات الأربعة متساوية. من البديهي للغاية ومعقول أن نخمن أن نوع السلسلة يزداد أيضًا تحميل HashCode () لإرجاع قيمة رمز التجزئة وفقًا لمحتوى السلسلة ، لذا فإن الأوتار ذات المحتوى نفسه لها نفس رمز التجزئة.
في الوقت نفسه ، يوضح هذا أيضًا سؤالًا: لماذا نحتاج إلى استخدام متساوين () للمقارنة عندما نعلم أن Hashcode () متساوية؟ فذلك لأنه يتجنب الموقف في المثال أعلاه ، لأنه وفقًا لتنفيذ الحمل الزائد لطريقة HashCode () لفئة الشخص ، ستستخدم فئة الشخص بشكل مباشر قيمة رمز التجزئة لمعرف عضو نوع السلسلة كقيمة رمز التجزئة. ومع ذلك ، فمن الواضح أن الشخص ("003") وسلسلة ("003") ليست متساوية ، لذلك عندما يكون Hashcode () متساويًا ، هناك حاجة أيضًا إلى المقارنة.
يمكن استخدام الأمثلة التالية كدليل على الوصف أعلاه:
System.out.println (شخص جديد ("003"). hashcode ()) ؛ // 47667system.out.println (سلسلة جديدة ("003"). hashcode ()) ؛ // 47667system.out.println (شخص جديد ("003"). يساوي (سلسلة جديدة ("003"))) ؛ // خطأ شنيعتستخدم المقالة أعلاه Java فئات مخصصة كمثال على القيمة الرئيسية لـ HashMap. هذا هو كل المحتوى الذي أشاركه معك. آمل أن يعطيك مرجعًا وآمل أن تتمكن من دعم wulin.com أكثر.