مقدمة
كما نعلم جميعًا ، لدى java.lang.object hashcode () وطريقة متساوية () ، والتي تلعب دورًا مهمًا في تصميم البرامج. أعد كتابة هاتين الطريقتين في بعض الفئات لإنجاز بعض الوظائف المهمة.
1. لماذا استخدام hashcode ()؟
العناصر في مجموعة المجموعة مضطربة وغير قابلة للتكرار. إذن ما هو الأساس للحكم على ما إذا كان هناك عنصرين يتكرران؟
يقول بعض الناس: Object.equal() يستخدم بالطبع لمقارنة ما إذا كانت الكائنات متساوية. ومع ذلك ، هناك عدد كبير من الكائنات في المجموعة ، وسيزيد عدد مقارنات عناصر الكائنات المضافة إلى المجموعة تدريجياً ، مما يقلل بشكل كبير من كفاءة عملية البرنامج. تستخدم Java خوارزمية التجزئة (تسمى أيضًا خوارزمية التجزئة) لحل هذه المشكلة. يتم تعيين الكائن (أو البيانات) مباشرة إلى عنوان وفقًا لخوارزمية معينة ، ويتم تحسين كفاءة الوصول إلى الكائن بشكل كبير.
وبهذه الطريقة ، عندما تحتاج مجموعة تحتوي على عدد كبير من العناصر إلى إضافة عنصر (كائن) ، اتصل أولاً بـ Hashcode () لهذا العنصر ، ويمكنك وضع موقع التخزين الفعلي لهذا العنصر في وقت واحد. إذا لم يكن هناك عنصر في هذا الموضع ، فهذا يعني أن هذا الكائن يتم تخزينه في المجموعة المحددة لأول مرة ، ويتم تخزين الكائن مباشرة في هذا الموضع ؛ إذا كان هناك كائن في هذا الموضع ، اتصل بـ equal () لمعرفة ما إذا كان الكائنان متساويان. إذا كان الشيء نفسه صحيحًا ، فتجاهل العنصر ولم يكن موجودًا. إذا لم يكن متساوًا ، فهو تجزئة للعناوين الأخرى.
هذا هو السبب أيضًا في أن مجموعة كائن SET تخزن بيانات نوع الكائن ، فمن الضروري ليس فقط إعادة كتابة طريقة HashCode () للكائن ولكن أيضًا إعادة كتابة طريقة متساوية ().
2. كيف تستخدم Hashcode ()؟
العلاقة بين قيمة إرجاع HashCode () و equals ()
هنا مثال. في تطوير البرمجيات الفعلية ، من الأفضل إعادة كتابة هاتين الطريقتين.
موظف الطبقة العامة {int amployeeId ؛ اسم السلسلة Override Public Boolean يساوي (كائن OBJ) {if (obj == this) إرجاع 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 () ؛ عودة التجزئة. }}تُستخدم طرق متساوية () و hashcode () للمقارنة في نفس الفئة ، خاصة عند تخزين كائن الفئة نفسه في الحاوية مثل تعيين الكائنات في نفس الفئة.
هنا نحتاج أولاً إلى فهم مشكلة:
يجب أن يكون كائنان ذوو المساواة () متساويًا ، وتجزئة الرمز () متساويًا ، ولا يمكن أن يثبت كائنان مع متساوي () لا يساوي ، أن Hashcode () ليس متساويًا. بمعنى آخر ، بالنسبة لكائنين لا يساويهم طريقة () ، قد يكون Hashcode () متساويًا.
هنا يشبه Hashcode فهرس كل حرف في القاموس ، ويساوي () مثل مقارنة الكلمات المختلفة تحت نفس الحرف في القاموس. كما هو الحال في القاموس ، البحث عن الكلمتين "الذات" و "عفوية" تحت كلمة "الذات" في القاموس ، إذا تم استخدام متساوي () لتحديد المساواة في الاستعلام عن الكلمات ، فهي نفس الكلمة. على سبيل المثال ، فإن الكلمتين المقارنتين بـ equals () هما "الذات" ، ثم يجب أن تكون القيم التي تم الحصول عليها بواسطة طريقة HashCode () متساوية في هذا الوقت ؛ إذا كانت الطريقة المتساوية () تقارن عبارة "الذات" و "عفوية" ، فإن النتيجة هي أنك لا تريد الانتظار ، لكن كلتا هذه الكلمتين تنتميان إلى الكلمات "ذاتية" وهكذا عند البحث عن الفهارس ، أي ، Hashcode () هو نفسه. إذا كان متساوي () يقارن عبارة "الذات" و "هم" ، فإن النتائج تختلف أيضًا ، والنتائج التي تم الحصول عليها بواسطة HashCode () تختلف أيضًا في هذا الوقت.
على العكس: Hashcode () مختلفة ، ويمكن تقديم متساوٍ () ؛ HashCode () متساوية ، قد يكون متساويًا () متساويًا أو قد لا يكون متساويًا.
في فئة الكائن ، فإن طريقة HashCode () هي طريقة محلية ، والتي تُرجع قيمة العنوان للكائن. تقارن طريقة تساوي () في فئة الكائن أيضًا قيم العنوان للكائنين. إذا كانت المساواة () متساوية ، فهذا يعني أن قيم العنوان للكائنين متساوية أيضًا. بالطبع ، hashcode () متساوية.
نظرًا لأن متساوٍ أكثر دقة لمقارنة العناصر المتساوية ، فلماذا تستخدم طريقة HashCode ()؟
لأن خوارزمية التجزئة توفر كفاءة عالية في العثور على عناصر ، إذا كنت ترغب في العثور على ما إذا كانت المجموعة تحتوي على كائن ، وكيفية كتابة رمز البرنامج التقريبي؟
عادةً ما تخرج كل عنصر واحد تلو الآخر لمقارنته بالكائن الذي تبحث عنه. عندما تجد أن نتيجة مقارنة طريقة متساوين بين عنصر والكائن الذي تبحث عنه ، توقف عن البحث وإرجاع المعلومات الإيجابية. خلاف ذلك ، إرجاع المعلومات السلبية. إذا كان هناك العديد من العناصر في المجموعة ، مثل 10000 عنصر ولا تحتوي على الكائن الذي تبحث عنه ، فهذا يعني أن برنامجك يحتاج إلى الحصول على 10000 عنصر من المجموعة ومقارنة واحدة تلو الأخرى للحصول على استنتاج.
تحدد فئة الكائن طريقة hashcode () لإرجاع رمز التجزئة لكل كائن Java. عند البحث عن كائن من مجموعة Hashset ، يقوم نظام Java أولاً باستدعاء طريقة HashCode () للكائن للحصول على جدول رمز التجزئة للكائن ، ثم يجد منطقة التخزين المقابلة بناءً على التجزئة ، وأخيراً يحصل على كل عنصر في منطقة التخزين ومقارنته مع الكائن لطريقة متساوية. وبهذه الطريقة ، يمكنك الحصول على الاستنتاج دون اجتياز جميع العناصر في المجموعة. يمكن ملاحظة أن مجموعة Hashset لها أداء جيد لاسترجاع الكائن.
ومع ذلك ، فإن كفاءة تخزين الكائنات في مجموعة hashset منخفضة نسبيًا ، لأنه عند إضافة كائن إلى مجموعة التجزئة ، يجب حساب رمز التجزئة للكائن أولاً ويتم تحديد موقع تخزين الكائن في المجموعة بناءً على رمز التجزئة هذا. من أجل التأكد من أنه يمكن تخزين كائنات المثيل للفئة بشكل طبيعي في hashset ، يجب أن تكون نتائج كائدي مثيل هذه الفئة متساوية عند مقارنتها بالطريقة المتساوية () متساوية ؛ أي إذا كانت نتيجة obj1.equals(obj2) صحيحة ، فيجب أن تكون نتيجة التعبير التالي true:obj1.hashCode() == obj2.hashCode() .
بمعنى آخر: عندما نعيد كتابة طريقة متساوية في الكائن ، يجب علينا إعادة كتابة طريقة Hashcode الخاصة به. إذا لم نقم بإعادة كتابة طريقة HashCode الخاصة بها ، فإن طريقة HashCode في كائن الكائن تُرجع دائمًا عنوان التجزئة لكائن ما ، وهذا العنوان لا يساوي أبدًا. لذا ، حتى إذا تم إعادة كتابة طريقة متساوية في هذا الوقت ، فلن يكون هناك أي تأثير محدد ، لأنه إذا كانت طريقة Hashcode لا تريد الانتظار ، فلن تسمي طريقة متساوية للمقارنة ، لذلك فهي لا معنى لها.
تستخدم معظم هياكل البيانات طريقة متساوية لتحديد ما إذا كانت تحتوي على عنصر ، على سبيل المثال:
قائمة <Tring> list = arrays.aslist ("A" ، "B" ، "C") ؛ Boolean يحتوي على = list.contains ("B") ؛ يحتوي هذا المتغير على نتيجة صحيحة لأنه ، على الرغم من أن "B" هي حالات مختلفة (بالإضافة إلى ذلك ، يتم تجاهل الإقامة السلسلة) ، فهي متساوية.
يستخدمون طريقة سريعة لمقارنة (تقليل المساواة المحتملة) بدلاً من مقارنة كل عنصر موجود في المثيل. تتطلب المقارنة السريعة فقط مقارنة الجوانب التالية:
مقارنة الاختصار تعني أنه من خلال مقارنة قيم التجزئة ، يمكن أن تحل محل مثيل بقيمة عدد صحيح. الحالات التي لها رمز التجزئة نفسها ليست بالضرورة متساوية ، ولكن يجب أن يكون للحالات ذات المساواة نفس قيمة التجزئة. (أو يجب أن يكون ، سنناقش هذا قريبًا) يتم تسمية هياكل البيانات هذه غالبًا من خلال هذه التقنية ، ويمكن التعرف عليها بواسطة Hash ، من بينها HashMap هي الممثل الأكثر شهرة.
عادة ما يعملون مثل هذا:
عند إضافة عنصر ، يتم استخدام رمز التجزئة لحساب فهرس الصفيف الداخلي (أي ، ما يسمى الجرافة)
إذا كانت الإجابة بنعم ، فإن العناصر غير المتكافئة لها نفس رمز التجزئة ، فهي تنتهي بها نفس الدلو وتجمعها معًا ، على سبيل المثال عن طريق إضافة إلى القائمة.
عند تنفيذ مثيل يحتوي على عمليات ، سيتم استخدام رمز التجزئة الخاص به لحساب قيمة الجرافة (قيمة الفهرس) ، وسيتم مقارنة المثيل فقط عند وجود العناصر في قيمة الفهرس المقابلة.
لذلك يساوي ، يتم تعريف hashcode في فئة الكائن.
إذا تم استخدام Hashcode كاختصار لتحديد المساواة ، فهناك شيء واحد فقط يجب أن نهتم به: يجب أن يكون للكائنات المتساوية نفس hashcode ، ولهذا السبب تجاوزنا طريقة متساوية ، علينا إنشاء تطبيق Hashcode الذي يطابقه!
خلاف ذلك قد لا يكون للكائنات المتساوية نفس رمز التجزئة ، لأنها ستسمي التنفيذ الافتراضي للكائن.
اقتبس من الوثائق الرسمية
اتفاقية Hashcode العامة:
عند استدعاء نفس الكائن الذي يعمل في تطبيق Java ، يجب أن تُرجع طريقة HashCode دائمًا نفس عدد صحيح. لا يلزم أن يكون هذا صحيحًا متسقًا عبر تطبيقات Java المختلفة. وفقًا لطريقة equals(Object) ، إذا كان كائنين متساويين ، فيجب أن ينتج الكائنان طريقة HashCode نفس النتيجة.
وفقًا لطريقة equals(Object) ، إذا لم يكن الكائنان متساويان ، فإن استدعاء طريقة HashCode لا ينتج بالضرورة نتائج عدد صحيح مختلف. ومع ذلك ، يجب أن يدرك المبرمجون أن إنتاج نتائج عدد صحيح مختلفة للكائنات غير المتكافئة من المحتمل أن يحسن أداء جدول التجزئة.
تنفيذ Hashcode
فيما يلي تطبيق بسيط لـ person.hashcode() :
Overridepublic int hashcode () {return objects.hash (firstName ، lastName) ؛}يحسب الشخص رمز التجزئة من خلال الجمع بين الحقول المتعددة. يتم حساب جميعها بواسطة وظيفة تجزئة الكائن.
حدد حقل
ولكن ما هي الحقول ذات الصلة؟ ستساعدنا المتطلبات في الإجابة على هذا السؤال:
إذا كان يجب أن يكون للكائن المساواة نفس رمز التجزئة ، فلن يتضمن رمز التجزئة المحسوب أي حقول غير مستخدمة لفحوصات المساواة. (وإلا ، فإن الكائنين هما أن هاتين الحقول مختلفة ولكنها قد لا تزال متساوية ، لكن رموز التجزئة للكائنين ستكون مختلفة في هذا الوقت.) وبالتالي فإن المجموعة الفرعية من الحقول المستخدمة عندما يجب أن تكون حقول مجموعة التجزئة متساوية. يتم استخدام نفس الحقول افتراضيًا ، ولكن هناك بعض التفاصيل التي يجب مراعاتها.
لخص
نحن نتفهم أن حساب رمز التجزئة هو ضغط قيمة عدد صحيح متساوٍ: يجب أن يكون للكائنات المتساوية نفس رمز التجزئة ، وبالنسبة لاعتبارات الأداء ، من الأفضل مشاركة رمز التجزئة نفسه مع عدد قليل من الكائنات غير المتساوية.
هذا يعني أنه إذا تمت إعادة كتابة طريقة متساوية ، فيجب إعادة كتابة طريقة HashCode.
عند تطبيق Hashcode يستخدم نفس الحقول المستخدمة في متساوية (أو مجموعة فرعية من الحقول المستخدمة في متساوية)
من الأفضل عدم تضمين الحقول القابلة للتغيير. لا تفكر في استدعاء Hashcode للمجموعات. إذا لم يكن هناك وضع محدد إدخال خاص ، فحاول استخدام خوارزمية التجزئة العامة.
حسنًا ، ما سبق هو المحتوى الكامل لهذه المقالة. آمل أن يكون لمحتوى هذه المقالة قيمة مرجعية معينة لدراسة أو عمل الجميع. إذا كان لديك أي أسئلة ، فيمكنك ترك رسالة للتواصل. شكرا لك على دعمك إلى wulin.com.