مبدأ العمل في Hashmap هو مسألة مقابلة Java شائعة في السنوات الأخيرة. يعرف كل مبرمج Java تقريبًا hashmap ، ويعرف مكان استخدام hashmap ، ويعرف الفرق بين hashtable و hashmap. فلماذا سؤال المقابلة هذا مميز جدا؟ هذا لأن هذا السؤال عميق جدا. غالبًا ما يظهر هذا السؤال في المقابلات المتقدمة أو المتوسطة. تفضل البنوك الاستثمارية طرح هذا السؤال وقد تطلب منك تنفيذ HashMap لفحص مهارات البرمجة الخاصة بك. إن إدخال ConcurrentHashMap وغيرها من مجموعات متزامنة يجعل هذه المشكلة أكثر تعقيدًا. لنبدأ رحلة الاستكشاف!
دعونا نمتلك بعض الأسئلة البسيطة أولاً
"هل استخدمت هاشماب؟" "ما هو hashmap؟ لماذا استخدمته؟"
سيجيب الجميع تقريبًا على "نعم" ، ثم يجيب على بعض ميزات HashMap ، مثل HashMap يمكن أن تقبل قيم وقيم مفتاح فارغة ، في حين أن Hashtable لا يمكن ؛ Hashmap غير متزامن. هاشماب سريع. ويخزن HashMap أزواج القيمة الرئيسية ، وما إلى ذلك. هذا يدل على أنك استخدمت hashmap وأن تكون على دراية بها. لكن القائم بإجراء المقابلة اتخذ منعطفًا سريعًا وبدأ في طرح بعض الأسئلة الصعبة من الآن فصاعدًا ، حول المزيد من التفاصيل الأساسية لـ HashMap. يجوز للمقابلة طرح الأسئلة التالية:
"هل تعرف كيف يعمل hashmap؟" "هل تعرف كيف تعمل طريقة الحصول على () HashMap؟"
قد تجيب ، "لم أكن أبحث عن واجهة برمجة تطبيقات Java القياسية بالتفصيل ، يمكنك إلقاء نظرة على رمز مصدر Java أو فتح JDK." "يمكنني العثور على الإجابة مع Google."
لكن قد يكون بعض المقابلات قادرين على إعطاء الإجابة ، "يعتمد HashMap على مبدأ التجزئة. نستخدم (المفتاح ، القيمة) لتخزين الكائنات في hashmap واستخدام GET (مفتاح) للحصول على كائنات من hashmap. عندما ننقل مفاتيح وقيم إلى طريقة but () ، فإننا ندعو إلى هاشكود () طريقة المفتاح ، والمعاد استخدامها للتجلب إلى المخزن. النقطة الأساسية هنا هي الإشارة إلى أن HashMap يخزن كائنات المفاتيح وكائنات القيمة في الجرافة كخريطة. هذا يساعد على فهم منطق الحصول على الكائنات. إذا لم تدرك هذا ، أو تعتقد عن طريق الخطأ أنك تخزن القيم فقط في الدلاء ، فلن تجيب على منطق كيفية الحصول على كائنات من HashMap. هذه الإجابة صحيحة تمامًا ، كما يوضح أن القائم بإجراء المقابلة يعرف التجزئة وكيف يعمل HashMap. ولكن هذه مجرد بداية القصة. عندما ينضم القائم بإجراء المقابلة إلى بعض المشاهد الفعلية التي يتعين على مبرمجي Java أن يواجهها كل يوم ، تظهر إجابات خاطئة بشكل متكرر. قد يكون السؤال التالي حول اكتشاف الاصطدام في HashMap وحل التصادم:
"ماذا يحدث عندما يكون رمز هش في كائنين هو نفسه؟" من هنا ، يبدأ الارتباك الحقيقي ، وسيجيب بعض المقابلات على أنه نظرًا لأن رمز الهاش هو نفسه ، فإن الكائنين متساوين ، وسوف يرمي Hashmap استثناءات ، أو لن يتم تخزينهما. ثم قد يذكرهم القائم بإجراء المقابلة أن هناك طريقتين: متساوون () و hashcode () ، ويخبرهم أنه حتى لو كان رمز الهاش هو نفسه ، فقد لا يكون متساوًا. قد يستسلم بعض المقابلات ، بينما يمكن للآخرين الاستمرار في التقدم. أجابوا ، "لأن رمز الهاش هو نفسه ، فإن وضع دلوهم هو نفسه ، وسيحدث" الاصطدام ". نظرًا لأن HashMap يستخدم قائمة مرتبطة لتخزين الكائنات ، سيتم تخزين هذا الإدخال (الخريطة. كائن الدخول الذي يحتوي على أزواج ذات قيمة رئيسية) في القائمة المرتبطة." هذه الإجابة معقولة جدا. على الرغم من وجود العديد من الطرق للتعامل مع التصادم ، فإن هذه الطريقة هي الأسهل ، وهي طريقة معالجة HashMap. لكن القصة لم تنته بعد ، وسيستمر القائم بإجراء المقابلة في السؤال:
"إذا كان رمز hashcode للمفتاحين هو نفسه ، فكيف تحصل على كائن القيمة؟" سيجيب القائم على المقابلة: عندما نسمي طريقة GET () ، سيستخدم HashMap رمز HashCode للكائن الرئيسي للعثور على موقع الجرافة ثم الحصول على كائن القيمة. يذكره القائم بإجراء المقابلة أنه إذا تم تخزين كائنين من القيمة في نفس الدلو ، فإنه يعطي الإجابة: سيتم اجتياز القائمة المرتبطة حتى يتم العثور على كائن القيمة. سوف يسأل المقابلة ، لأنه ليس لديك كائن قيمة للمقارنة ، كيف حددت ما إذا كنت ستجد كائن القيمة؟ ما لم يخزن القائم بإجراء المقابلة أزواج القيمة الرئيسية في القائمة المرتبطة حتى يخزنها HashMap في القائمة المرتبطة ، فلن يتمكنوا من الإجابة على هذا السؤال.
سيقول بعض المقابلات الذين يتذكرون نقطة المعرفة المهمة أنه بعد العثور على موقع الجرافة ، سوف يطلقون على المفاتيح. الجواب المثالي!
في كثير من الحالات ، سوف يرتكب المقابلات أخطاء في هذا الرابط لأنهم يخلطون بين الأساليب hashcode () و equals (). لأنه قبل أن يظهر HashCode () بشكل متكرر ، وتظهر طريقة متساوية () فقط عند الحصول على كائن القيمة. سيشير بعض المطورين الممتازين إلى أن استخدام الكائنات غير القابلة للتغيير والمعلنة على أنها نهائية ، واستخدام أساليب المساواة المناسبة () و HashCode () سيقلل من حدوث تصادمات وتحسين الكفاءة. تتيح عدم التثبيت رمز التجزئة للمفاتيح المختلفة للتخزين المؤقت ، مما سيزيد من سرعة الحصول على الكائن بأكمله. يعد استخدام فئات Wrapper مثل String و Interger As Keys اختيارًا جيدًا جدًا.
إذا كنت تعتقد أن الأمر قد انتهى هنا ، فسوف تفاجأ عندما تسمع السؤال التالي. "ماذا لو تجاوز حجم hashmap السعة المحددة بواسطة عامل التحميل؟" ما لم تكن تعرف حقًا كيف يعمل HashMap ، فلن تجيب على هذا السؤال. حجم عامل التحميل الافتراضي هو 0.75. وهذا يعني أنه عندما تملأ الخريطة 75 ٪ من الدلاء ، مثل فئات التجميع الأخرى (مثل ArrayList ، وما إلى ذلك) ، سيتم إنشاء مجموعة دلو التي يبلغ حجمها ضعف حجم hashmap الأصلي لتغيير حجم الخريطة ووضع الكائن الأصلي في مجموعة الجرافة الجديدة. تسمى هذه العملية إعادة صياغة لأنها تسمي طريقة التجزئة للعثور على موقع الجرافة الجديد.
إذا تمكنت من الإجابة على هذا السؤال ، يأتي السؤال التالي: "هل تفهم ما هي المشكلات الموجودة في تغيير حجم HashMap؟" قد لا تكون قادرًا على الإجابة عليه. في هذا الوقت ، سوف يذكرك القائم بإجراء المقابلة بأنه عندما يكون هناك متعددة الخيوط ، قد يكون هناك حالة سباق.
عند تغيير حجم HashMap ، هناك بالفعل منافسة مشروطة ، لأنه إذا وجد كلا الموضوعين أن HashMap يحتاج إلى تغيير حجمه ، فسوف يحاولان تغيير الحجم في نفس الوقت. أثناء عملية تغيير الحجم ، سيتم عكس ترتيب العناصر المخزنة في القائمة المرتبطة ، لأنه عند الانتقال إلى وضع الجرافة الجديد ، لا يضع HashMap العناصر في نهاية القائمة المرتبطة ، ولكن في الرأس ، وهو تجنب عبور الذيل. إذا حدثت منافسة مشروطة ، فهناك دورة مفرغة. في هذا الوقت ، يمكنك أن تسأل القائم بإجراء المقابلة لماذا من الغريب أن تحتاج إلى استخدام HashMap في بيئة متعددة الخيوط؟ سائدا
يساهم القراء المتحمسون بمزيد من الأسئلة حول hashmap:
1. لماذا فئات الغلاف مثل String و Interger مناسبة كمفاتيح؟ فئة Wrapper مثل String و Interger هي الأنسب كمفتاح HashMap ، والسلسلة هي الأكثر استخدامًا. لأن السلسلة غير قابلة للتغيير والنهائي ، وتم إعادة كتابة أساليب المساواة () و HashCode (). فصول غلاف أخرى لديها أيضا هذه الميزة. التثبيت ضروري لأنه من أجل حساب Hashcode () ، يجب أن تمنع القيمة الرئيسية من التغيير. إذا كانت قيمة المفتاح تُرجع رمزًا مختلفًا عند وضعه والحصول عليه ، فلا يمكنك العثور على الكائن الذي تريده من HashMap. الثبات له مزايا أخرى مثل سلامة الخيط. إذا كان بإمكانك ضمان عدم تغيير رمز hashcode بمجرد إعلان حقل كنهائي ، فيرجى القيام بذلك. نظرًا لأن أساليب المساواة () و hashcode () يتم استخدامها عند الحصول على الكائنات ، من المهم جدًا إعادة كتابة هاتين الطريقتين بشكل صحيح. إذا عاد كائنان غير متكافئين إلى هاشكات مختلفة ، فستكون فرصة التصادم أصغر ، مما يمكن أن يحسن أداء hashmap.
2. هل يمكننا استخدام كائنات مخصصة كمفاتيح؟ هذا امتداد للسؤال السابق. بالطبع ، يمكنك استخدام أي كائن كمفاتيح طالما أنه يتبع قواعد تعريف أساليب Equals () و HashCode () ولن يتغير مرة أخرى بعد إدراج الكائن في الخريطة. إذا كان هذا الكائن المخصص غير قابل للتغيير ، فإنه يفي بالفعل بالحالة كمفتاح لأنه لا يمكن تغييره بعد إنشائه.
3. هل يمكننا استخدام CocurrentHashMap لاستبدال علامة التصنيف؟ هذا سؤال مقابلة شائع للغاية ، لأن المزيد والمزيد من الناس يستخدمون concurrenthashmap. نحن نعلم أن علامة التجزئة متزامنة ، ولكن تزامن التزامن هو أفضل لأنه يغلق جزءًا من الخريطة بناءً على مستوى التزامن. يمكن أن يحل ConcurrenthashMap بالتأكيد محل علامة التصنيف ، لكن علامة التجزئة توفر سلامة خيط أقوى. تحقق من هذه المدونة لمعرفة الفرق بين علامة التجزئة و concurrenthashmap.
أنا شخصياً أحب هذا السؤال كثيرًا لأن عمق واتساع هذا السؤال لا ينطوي بشكل مباشر على مفاهيم مختلفة. دعونا نلقي نظرة على نقاط المعرفة حول تصميم هذه الأسئلة:
لخص
كيف يعمل hashmap
يعتمد HashMap على مبدأ التجزئة ، ونخزن ونحصل على الأشياء من خلال BUT () والحصول على () الأساليب. عندما نقوم بتمرير زوج القيمة الرئيسية إلى طريقة PUT () ، فإنه يستدعي طريقة HashCode () للكائن الرئيسي لحساب رمز التجزئة ، ثم يجد موضع الجرافة لتخزين كائن القيمة. عند الحصول على الكائن ، يتم العثور على زوج القيمة المفتاح الصحيح من خلال طريقة متساوٍ () للكائن الرئيسي ، ثم يتم إرجاع كائن القيمة. يستخدم HashMap قوائم مرتبطة لحل مشكلة الاصطدام. عند حدوث تصادم ، سيتم تخزين الكائن في العقدة التالية من القائمة المرتبطة. يقوم HashMap بتخزين كائنات زوج المفاتيح في كل عقدة قائمة مرتبطة.
ماذا يحدث عندما يكون رمز هش في كائنين مختلفين مختلفين هو نفسه؟ سيتم تخزينها في القائمة المرتبطة في نفس موقع الجرافة. يتم استخدام طريقة equals () للكائن الرئيسي للعثور على أزواج القيمة الرئيسية.
نظرًا لأن HashMap له العديد من الفوائد ، فقد استخدمت HashMap كذاكرة التخزين المؤقت في تطبيقات التجارة الإلكترونية. نظرًا لأن Java يستخدم كثيرًا في المجال المالي ، وبالنسبة لاعتبارات الأداء ، فإننا نستخدم غالبًا hashmap و concurrenthashmap. يمكنك عرض المزيد من المقالات حول hashmap:
الفرق بين hashmap و hashtable
الفرق بين hashmap و hashset
الرابط الأصلي: Javarevisited Translation: ImportNew.com - Tang Xiaojuan Translation Link: http://www.importnew.com/7099.html