مقارنة HashMap وHashtable في Java: الاختلافات الرئيسية والكفاءة

مقارنة HashMap وHashtable في Java: الاختلافات الرئيسية والكفاءة
Java

فهم HashMap وHashtable في جافا

في عالم مجموعات Java، يعد HashMap وHashtable من بنيات البيانات المستخدمة على نطاق واسع لتخزين أزواج القيمة الرئيسية. على الرغم من أنها قد تبدو متشابهة، إلا أنها تحتوي على اختلافات واضحة يمكن أن تؤثر على أداء التطبيق الخاص بك وسلامة الخيط. يعد فهم هذه الاختلافات أمرًا بالغ الأهمية لاختيار الاختلاف المناسب لاحتياجاتك.

تتعمق هذه المقالة في الفروق الرئيسية بين HashMap وHashtable، وتستكشف وظائفها وكفاءتها وملاءمتها للتطبيقات غير المترابطة. في النهاية، سيكون لديك فكرة أوضح عن بنية البيانات التي ستستخدمها في حالة الاستخدام المحددة الخاصة بك.

يأمر وصف
HashMap.put() إدراج زوج من القيمة الرئيسية في HashMap. يسمح بالمفاتيح والقيم الفارغة.
Hashtable.put() إدراج زوج من القيمة الرئيسية في Hashtable. لا يسمح بالمفاتيح أو القيم الفارغة.
System.nanoTime() تُرجع القيمة الحالية لمصدر الوقت عالي الدقة لجهاز Java Virtual Machine قيد التشغيل، بالنانو ثانية.
try { ... } catch (NullPointerException e) يحاول تنفيذ التعليمات البرمجية ويلتقط أي NullPointerExceptions، ويتعامل مع الحالات التي يتم فيها استدعاء Hashtable.put() بقيم فارغة.
HashMap.get() يسترد القيمة المرتبطة بمفتاح محدد من HashMap.
Hashtable.get() استرداد القيمة المرتبطة بمفتاح محدد من Hashtable.

الغوص العميق في تنفيذ HashMap وHashtable

يوفر البرنامج النصي الأول مقارنة مباشرة بين HashMap و Hashtable في جافا. يبدأ البرنامج النصي باستيراد الفئات الضرورية وإنشاء مثيلات لكلا بنيات البيانات. أ HashMap يتم إنشاء مثيل له وملؤه بأزواج القيمة الرئيسية. وبالمثل، أ Hashtable يتم إنشاؤها وسكانها. يوضح هذا البرنامج النصي الفرق الأساسي في التعامل مع القيم الخالية. HashMap.put() يسمح بإدراج قيم فارغة دون مشاكل، في حين أن Hashtable.put() يلقي أ NullPointerException إذا تمت محاولة إضافة مفاتيح أو قيم فارغة. ال try { ... } catch (NullPointerException e) يتم استخدام الكتل لتوضيح هذا السلوك. يساعد البرنامج النصي المطورين على فهم متى ولماذا تعتبر القيم الخالية أحد الاعتبارات عند الاختيار بين بنيتي البيانات هاتين.

يركز البرنامج النصي الثاني على اختبار أداء HashMap و Hashtable في بيئة غير مترابطة. يبدأ الأمر بتهيئة كلتا الخريطتين وقياس الوقت المستغرق لإدراج مليون زوج من القيمة الرئيسية باستخدام System.nanoTime(). يساعد قياس الوقت عالي الدقة هذا في التقاط الوقت الدقيق المستغرق للعمليات. تتم طباعة النتائج على وحدة التحكم، مما يوضح الأداء النسبي. يقيس البرنامج النصي أيضًا وقت الاسترداد لنفس مجموعة المفاتيح من بني البيانات. ومن خلال مقارنة هذه الأوقات، يمكن للمطورين قياس بنية البيانات التي تحقق أداءً أفضل في التطبيقات غير المترابطة. يعد هذا البرنامج النصي مفيدًا بشكل خاص لضبط الأداء وفهم الحمل المرتبط به Hashtable بسبب أساليبها المتزامنة.

مقارنة HashMap وHashtable: الاختلافات الأساسية وحالات الاستخدام

تنفيذ جافا للمقارنة

import java.util.HashMap;
import java.util.Hashtable;

public class MapComparison {
    public static void main(String[] args) {
        // Creating a HashMap
        HashMap<String, String> hashMap = new HashMap<>();
        hashMap.put("1", "One");
        hashMap.put("2", "Two");
        hashMap.put("3", "Three");

        // Creating a Hashtable
        Hashtable<String, String> hashtable = new Hashtable<>();
        hashtable.put("A", "Apple");
        hashtable.put("B", "Banana");
        hashtable.put("C", "Cherry");

        // Displaying the HashMap
        System.out.println("HashMap: " + hashMap);

        // Displaying the Hashtable
        System.out.println("Hashtable: " + hashtable);

        // Checking for null values
        try {
            hashMap.put(null, "NullValue");
            System.out.println("HashMap allows null values: " + hashMap);
        } catch (NullPointerException e) {
            System.out.println("HashMap does not allow null values");
        }
        try {
            hashtable.put(null, "NullValue");
            System.out.println("Hashtable allows null values: " + hashtable);
        } catch (NullPointerException e) {
            System.out.println("Hashtable does not allow null values");
        }
    }
}

HashMap مقابل Hashtable: الأداء في البيئات ذات الخيوط المفردة

اختبار أداء Java للتطبيقات غير المترابطة

import java.util.HashMap;
import java.util.Hashtable;

public class PerformanceTest {
    public static void main(String[] args) {
        // Initializing the maps
        HashMap<Integer, Integer> hashMap = new HashMap<>();
        Hashtable<Integer, Integer> hashtable = new Hashtable<>();

        // Adding elements to HashMap
        long startTime = System.nanoTime();
        for (int i = 0; i < 1000000; i++) {
            hashMap.put(i, i);
        }
        long endTime = System.nanoTime();
        System.out.println("HashMap time: " + (endTime - startTime) + " ns");

        // Adding elements to Hashtable
        startTime = System.nanoTime();
        for (int i = 0; i < 1000000; i++) {
            hashtable.put(i, i);
        }
        endTime = System.nanoTime();
        System.out.println("Hashtable time: " + (endTime - startTime) + " ns");

        // Retrieving elements from HashMap
        startTime = System.nanoTime();
        for (int i = 0; i < 1000000; i++) {
            hashMap.get(i);
        }
        endTime = System.nanoTime();
        System.out.println("HashMap retrieval time: " + (endTime - startTime) + " ns");

        // Retrieving elements from Hashtable
        startTime = System.nanoTime();
        for (int i = 0; i < 1000000; i++) {
            hashtable.get(i);
        }
        endTime = System.nanoTime();
        System.out.println("Hashtable retrieval time: " + (endTime - startTime) + " ns");
    }
}

HashMap وHashtable: المزامنة وسلامة الخيط

أحد الاختلافات الرئيسية بين HashMap و Hashtable هو نهجهم في المزامنة وسلامة الخيط. Hashtable متزامن، مما يعني أنه آمن لسلسلة الرسائل ويمكن مشاركته بين سلاسل رسائل متعددة دون التسبب في مشكلات في التزامن. يتم تحقيق هذه المزامنة من خلال مزامنة معظم أساليبها، مما يضمن أن مؤشر ترابط واحد فقط يمكنه الوصول إلى جدول التجزئة في أي وقت محدد. ومع ذلك، فإن هذا يؤدي أيضًا إلى زيادة في الأداء بسبب آلية القفل Hashtable أبطأ مقارنة ب HashMap في سيناريوهات مترابطة واحدة.

في المقابل، HashMap غير متزامن وبالتالي فهو غير آمن لمؤشر الترابط. اذا كان HashMap يتم الوصول إليه من خلال عدة سلاسل رسائل في وقت واحد، فهناك خطر عدم تناسق البيانات وظروف السباق. لصنع HashMap خيط آمن، يمكن للمطورين استخدامه Collections.synchronizedMap() لتغليفها في خريطة متزامنة، أو يمكنهم استخدام ConcurrentHashMap تم تقديم فئة في Java 1.5، والتي توفر أداءً أفضل من خلال السماح بالوصول المتزامن إلى أجزاء مختلفة من الخريطة. هذا يجعل ConcurrentHashMap خيار أكثر كفاءة للتطبيقات المتزامنة.

الأسئلة المتداولة حول HashMap وHashtable

  1. ما هو الفرق الرئيسي بين HashMap وHashtable؟
  2. HashMap غير متزامن ويسمح بالمفاتيح والقيم الفارغة، بينما Hashtable متزامن ولا يسمح بالمفاتيح أو القيم الفارغة.
  3. أيهما أسرع في بيئة ذات ترابط واحد؟
  4. HashMap يكون أسرع بشكل عام في بيئة ذات ترابط واحد بسبب نقص حمل المزامنة.
  5. كيف يمكنك جعل مؤشر HashMap آمنًا؟
  6. باستخدام Collections.synchronizedMap() لتغليف HashMap أو باستخدام ConcurrentHashMap.
  7. هل يمكن لـ Hashtable تخزين المفاتيح أو القيم الفارغة؟
  8. لا، Hashtable لا يسمح بالمفاتيح أو القيم الفارغة وسيرمي ملف NullPointerException إذا حاولت.
  9. متى يجب عليك استخدام Hashtable على HashMap؟
  10. يستخدم Hashtable عندما يكون أمان مؤشر الترابط مطلوبًا ولا تشعر بالقلق بشأن الحمل الزائد لأداء المزامنة.
  11. هل يعد ConcurrentHashMap بديلاً أفضل لـ Hashtable؟
  12. نعم، ConcurrentHashMap يوفر التزامن والأداء أفضل مقارنة بـ Hashtable.
  13. لماذا لا يعتبر HashMap آمنًا لمؤشر الترابط؟
  14. HashMap تم تصميمه للسيناريوهات ذات الترابط الواحد ولا يتضمن آليات المزامنة.
  15. كيف يتعامل HashMap وHashtable مع التصادمات؟
  16. كلاهما HashMap و Hashtable التعامل مع التصادمات باستخدام التسلسل، حيث تحتوي كل مجموعة على قائمة مرتبطة من الإدخالات.

الأفكار النهائية حول HashMap وHashtable

يخدم HashMap وHashtable أغراضًا متشابهة في تخزين أزواج القيمة الرئيسية، لكنهما يختلفان بشكل كبير في أسلوبهما في المزامنة والأداء. يُفضل HashMap للتطبيقات غير المترابطة نظرًا لسرعته ومرونته مع القيم الخالية. على العكس من ذلك، يعد Hashtable مناسبًا للعمليات الآمنة للخيط ولكن على حساب الأداء. من خلال فهم هذه الاختلافات، يمكن للمطورين اتخاذ قرارات مستنيرة بشأن بنية البيانات التي سيتم استخدامها بناءً على متطلباتهم المحددة.