JavaRush /مدونة جافا /Random-AR /قصة مقابلة واحدة: أسئلة مثيرة للاهتمام
GuitarFactor
مستوى
Санкт-Петербург

قصة مقابلة واحدة: أسئلة مثيرة للاهتمام

نشرت في المجموعة
أتيحت لي الفرصة مؤخرًا لحضور مقابلة لشغل منصب متدرب في إحدى شركات تكنولوجيا المعلومات الكبرى. قصة مقابلة واحدة: أسئلة مثيرة للاهتمام - 1كانت هذه أول مقابلة لي في مجال تكنولوجيا المعلومات، وفي رأيي، اتضح أنها مثيرة للاهتمام. في المجموع، تم "استجوابي" لأكثر من 3 ساعات (سبق ذلك واجب منزلي واختبار في المكتب على الكمبيوتر). أريد أن أشيد بالمحاور الذي لم يستسلم عندما أجبت على السؤال بشكل غير صحيح، ولكن بمساعدة أسئلته الإرشادية أجبرني على التفكير والتوصل إلى الإجابة الصحيحة. سأقدم أدناه العديد من "الرسومات" - في رأيي، أسئلة مثيرة للاهتمام للغاية، وقد أعطاني بعضها فهمًا أعمق لجوانب معينة في Java. ربما تبدو هذه الأمور واضحة للبعض، لكن أعتقد أنه سيكون هناك من سيكون هذا مفيداً لهم. أسفل العبارات تم تمييزها بالخطوط التالية: المحاور - بالخط العريض شرح التعليق الصوتي وأفكاري - بخط مائل إجاباتي - بالخط العادي لقد انتهينا من الخلفية، فلنبدأ العمل)

رسم 1. "طريقة تبدو بسيطة"

اكتب كيف ستنفذ طريقة ترجع نتيجة قسمة الرقم أ على الرقم ب. يكتب القائم بالمقابلة على قطعة من الورق
int divide(int a, int b) {
}
* ألقيت نظرة متشككة على قطعة الورق التي تحمل توقيع الطريقة. ما الفائدة؟ * أكتب:
int divide(int a, int b) {
    return a/b;
}
هل هناك أي مشاكل مع هذه الطريقة؟ *لقد أمسكت بشخص غبي حقًا* على ما يبدو لا.. ويأتي بعد ذلك سؤال مشروع: ماذا لو كان b=0؟ *واو، أنا على وشك أن أطرد من هذا المكتب إذا واصلت هذا الأمر!* أوه نعم، بالطبع. لدينا هنا وسيطات من النوع int، لذلك سيتم طرح استثناء حسابي. إذا كانت الوسائط من النوع float أو double، فستكون النتيجة Infinity. ماذا سنفعل حيال هذا؟ لقد بدأت في كتابة محاولة/التقاط
int divide(int a, int b) {
    try {
        return a/b;
    } catch (Exception e) {
        e.printStackTrace();
        return ... // ??? what the hack?
    }
}
*يجب علي العودة والتجميد: يجب إرجاع شيء ما في حالة حدوث خطأ. ولكن كيف يمكن تمييز هذا "الشيء" عن نتيجة الحساب؟ * ماذا سنعود؟ حسنًا... أود أن أغير نوع متغير الإرجاع إلى عدد صحيح وفي حالة وجود استثناء سأرجعه فارغًا. لنتخيل أننا لا نستطيع تغيير النوع. هل يمكننا الخروج بطريقة ما؟ ربما يمكننا أن نفعل شيئا آخر مع الاستثناء؟ *هنا يأتي* يمكننا أيضًا إعادة توجيهه إلى طريقة الاتصال! يمين. ماذا سيكون شكلها؟
int divide(int a, int b) throws ArithmeticException{
    return a/b;
}

void callDivide(int a, int b) {
    try {
        divide(a, b);
    } catch (ArithmeticException e) {
        e.printStackTrace();
    }
}
هل من الضروري التعامل مع الاستثناء؟ نعم، لأننا نعيد توجيهها بشكل صريح من طريقة القسمة. (*لقد كنت مخطئًا هنا! ما يلي هو الأسئلة الاسترشادية التي يطرحها القائم بالمقابلة للوصول إلى الإجابة الصحيحة*) والاستثناء الحسابي - ما هو نوع الاستثناء - محدد أم غير محدد؟ هذا استثناء لوقت التشغيل، مما يعني أنه لم يتم تحديده. *هنا يأتي السؤال القاتل* فتبين، على حد تعبيرك، أننا إذا حددنا استثناءً حسابيًا في توقيع الطريقة، فإنه أصبح استثناءً محددًا؟ *آه!* ربما... لا. نعم، لقد ذهب. إذا أشرنا إلى الرميات /الاستثناء غير المحدد/ في التوقيع، فإننا نحذر فقط من أن الطريقة يمكنها طرح استثناء، ولكن ليس من الضروري التعامل معه في طريقة الاستدعاء. لقد تم حل هذا الأمر. هل هناك أي شيء آخر يمكننا القيام به لتجنب الأخطاء؟ *بعد تفكير طويل* نعم، يمكننا أيضًا التحقق مما إذا كانت (b==0). وتنفيذ بعض المنطق. يمين. لذلك يمكننا أن نذهب إلى 3 طرق:
  • حاول/قبض
  • رميات – إعادة التوجيه إلى طريقة الاستدعاء
  • فحص الحجة
في هذه الحالة، divideما هي الطريقة الأفضل في نظرك؟
سأختار إعادة توجيه الاستثناء إلى طريقة الاستدعاء، لأن... في طريقة القسمة، ليس من الواضح كيفية معالجة هذا الاستثناء ونوع النتيجة intالتي سيتم إرجاعها في حالة حدوث خطأ. وفي طريقة الاستدعاء، سأستخدم الوسيطة b للتحقق مما إذا كانت تساوي الصفر. يبدو أن هذه الإجابة أرضت الشخص الذي أجريت معه المقابلة، ولكن بصراحة، لست متأكدا من أن هذه الإجابة لا لبس فيها))

رسم 2. "من هو الأسرع؟"

بعد السؤال القياسي، كيف تختلف قائمة ArrayList عن LinkedList، جاء هذا: ما الذي سيحدث بشكل أسرع - إدراج عنصر في المنتصف ArrayListأو في المنتصف LinkedList؟ *هنا قفزت، وتذكرت أنني قرأت في كل مكان شيئًا مثل "استخدم LinkedListلإدراج أو إزالة العناصر في منتصف القائمة". في المنزل، قمت أيضًا بمراجعة محاضرات JavaRush مرة أخرى، وهناك عبارة: "إذا كنت ستقوم بإدراج (أو حذف) العديد من العناصر في منتصف المجموعة، فمن الأفضل أن تستخدم LinkedList. وفي جميع الحالات الأخرى - ArrayList." تم الرد تلقائيًا* سيكون الأمر أسرع مع LinkedList. وضح من فضلك
  1. من أجل إدراج عنصر في المنتصف ArrayList، نجد العنصر في القائمة في زمن ثابت، ثم نعيد حساب مؤشرات العناصر الموجودة على يمين العنصر المدرج، في الزمن الخطي.
  2. لـ LinkedList.. نصل أولاً إلى المنتصف في زمن خطي ثم ندخل عنصرًا في زمن ثابت، مع تغيير الروابط للعناصر المجاورة.
لذلك اتضح، أيهما أسرع؟ حسنًا... اتضح نفس الشيء. ولكن متى يكون LinkedListأسرع؟ اتضح أنه عندما نقوم بإدراجه في النصف الأول من القائمة. على سبيل المثال، إذا قمت بإدراجه في البداية، ArrayListفسيتعين عليك إعادة حساب جميع المؤشرات حتى الذيل، ولكن LinkedListسيتعين عليك فقط تغيير مرجع العنصر الأول. أخلاقيًا: لا تصدق حرفيًا كل ما هو مكتوب، حتى في JavaRush!)

رسم 3. "أين سنكون بدون رموز المساواة ورمز التجزئة!"

كانت المحادثة حول يساوي ورمز التجزئة طويلة جدًا - كيفية تجاوزها، وما هو التنفيذ Object، وما يحدث تحت الغطاء، عندما يتم إدراج عنصر في HashMap، وما إلى ذلك. سأقدم فقط عددًا من النقاط المثيرة للاهتمام في رأيي* تخيل أننا أنشأنا فصلًا دراسيًا
public class A {
    int id;

    public A(int id) {
        this.id = id;
    }
}
ولم يتجاوزوا equalsو hashcode. وصف ما سيحدث عند تنفيذ التعليمات البرمجية
A a1 = new A(1);
A a2 = new A(1);
Map<A, String> hash = new HashMap<>();
hash.put(a1, "1");
hash.get(a2);
*من الجيد أنني أمضيت بضعة أيام على وجه التحديد قبل المقابلة في فهم الخوارزميات الأساسية وتعقيدها وهياكل البيانات - لقد ساعدني ذلك كثيرًا، شكرًا CS50!*
  1. إنشاء مثيلين من الفئة أ

  2. نقوم بإنشاء خريطة فارغة تحتوي افتراضيًا على 16 سلة. المفتاح هو كائن من الفئة A، حيث لا يتم تجاوز equalsالأساليب hashcode.

  3. ضعها a1في الخريطة. للقيام بذلك، نقوم أولا بحساب التجزئة a1.

    ماذا سيكون التجزئة مساوياً؟

    عنوان الخلية في الذاكرة هو تطبيق لطريقة من فئةObject

  4. بناءً على التجزئة، نقوم بحساب مؤشر السلة.

    كيف يمكننا حساب ذلك؟

    *للأسف لم أعط إجابة واضحة هنا. لديك رقم طويل - تجزئة، وهناك 16 مجموعة - كيفية تحديد فهرس بحيث يتم توزيع الكائنات ذات التجزئة المختلفة بالتساوي عبر المجموعات؟ أستطيع أن أتخيل أن المؤشر يتم حسابه على النحو التالي:

    int index = hash % buckets.length

    لقد رأيت بالفعل في المنزل أن التنفيذ الأصلي في الكود المصدري مختلف قليلاً:

    static int indexFor(int h, int length)
    {
        return h & (length - 1);
    }
  5. نتحقق من عدم وجود تصادمات ونقوم بإدخال a1.

  6. دعنا ننتقل إلى الطريقة get. يتم ضمان أن يكون للمثيلين a1 وa2 عنوان مختلف hash(عنوان مختلف في الذاكرة)، لذلك لن نجد أي شيء لهذا المفتاح

    ماذا لو قمنا بإعادة تعريفه فقط hashcodeفي الفئة A وحاولنا إدراج زوج في الهاشماب أولاً بالمفتاح a1، ثم بالمفتاح a2؟

    ثم سنجد أولاً السلة المطلوبة hashcode- سيتم تنفيذ هذه العملية بشكل صحيح. بعد ذلك، لنبدأ في استعراض الكائنات Entryالموجودة في LinkedList المرفقة بعربة التسوق ومقارنة المفاتيح حسب equals. لأن equalsلم يتم تجاوزه، فسيتم أخذ التنفيذ الأساسي من الفصل Object- المقارنة حسب المرجع. نضمن أن يكون لـ a1 وa2 روابط مختلفة، لذلك "سنفقد" العنصر المدرج a1، وسيتم وضع a2 في LinkedList كعقدة جديدة.

    ما هو الاستنتاج؟ هل من الممكن استخدامه كمفتاح في HashMapكائن غير متجاوز equalshashcode؟

    لا لا يمكنك.

رسم 4. "دعونا نكسرها عن قصد!"

بعد الأسئلة حول الخطأ والاستثناء، يتبع السؤال التالي: اكتب مثالاً بسيطًا حيث سترمي الدالة StackOverflow. * ثم تذكرت كيف أصابني هذا الخطأ عندما كنت أحاول كتابة بعض الوظائف العودية * من المحتمل أن يحدث هذا في حالة الاستدعاء العودي، إذا تم تحديد شرط الخروج من العودية بشكل غير صحيح. *ثم بدأت بتجربة شيء ذكي، وفي النهاية ساعدني القائم بإجراء المقابلة، وتبين أن كل شيء بسيط*
void sof() {
    sof();
}
كيف يختلف هذا الخطأ عن OutOfMemory؟ * لم أجب هنا، فقط أدركت لاحقًا أن هذا سؤال يتعلق بمعرفة Stackذاكرة HeapJava (يتم تخزين الاستدعاءات والمراجع للكائنات في المكدس، ويتم تخزين الكائنات نفسها في ذاكرة الكومة). وفقًا لذلك، يتم طرح StackOverflow عندما لا يكون هناك مساحة إضافية في Stackالذاكرة لاستدعاء الطريقة التالية، OutOfMemoryونفاد المساحة المخصصة للكائنات في Heapالذاكرة*
هذه هي اللحظات التي أتذكرها من المقابلة. في النهاية، تم قبولي للتدريب الداخلي، لذلك أمامي شهرين ونصف من التدريب، وإذا سار كل شيء على ما يرام، سأحصل على وظيفة في الشركة) إذا كان هناك اهتمام، يمكنني كتابة مقال آخر، هذه المرة أصغر، مع تحليل لمشكلة بسيطة لكن توضيحية حصلت على مقابلة في شركة أخرى. هذا كل شيء بالنسبة لي، وآمل أن يساعد هذا المقال أي شخص على تعميق معرفته أو تنظيمها. تعلم سعيد للجميع!
تعليقات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION