TreeMap و LinkedHashMap
TreeMap و LinkedHashMap
تعرفت سابقًا على HashMap: سريعة ولا ترتيب لها. لكن أحيانًا تحتاج أكثر من مجرد بحث سريع — تريد أن تخرج المفاتيح بترتيب يمكن التنبّؤ به. يوفّر Java تطبيقَين لواجهة Map يحلّان هذه المشكلة بطريقتين مختلفتين: TreeMap يحتفظ بالمفاتيح مرتّبة وفق ترتيبها الطبيعي أو مُقارِن مخصّص، بينما LinkedHashMap يحافظ على ترتيب إدراج المفاتيح.
لماذا يهمّنا الترتيب؟
تخيّل أنك تبني لوحة نتائج، أو قاموسًا مرتّبًا، أو ذاكرة تخزين مؤقت تُزيل الإدخال الأقدم أولًا. لا يضمن HashMap العادي أي ترتيب — قد تخرج العناصر بأي تسلسل. اختيار الخريطة المرتّبة المناسبة يجعل نيّتك صريحة ويُلغي خطوات الفرز المرهقة لاحقًا.
TreeMap — مرتّب حسب المفتاح
يعتمد TreeMap<K, V> داخليًا على شجرة Red-Black. كل عملية put وget تستغرق O(log n) بدلًا من O(1) المُخفَّف في خريطة التجزئة، لكن في المقابل تبقى الخريطة مرتّبة في كل الأوقات.
لأن الشجرة مرتّبة دائمًا، يكشف TreeMap عن مجموعة غنية من دوال التنقّل التي لا تتوفّر في الخرائط العادية:
TreeMap واجهة NavigableMap التي تضيف: floorKey وceilingKey وlowerKey وhigherKey وheadMap وtailMap وsubMap. صرّح بمتغيّراتك كـ NavigableMap<K,V> عندما تريد كشف هذه الدوال للمستدعِين.
ترتيب مخصّص باستخدام Comparator
عندما تحتاج ترتيبًا مختلفًا — كالترتيب الأبجدي العكسي أو الترتيب غير الحساس لحالة الأحرف — مرّر Comparator إلى المُنشئ:
Comparable ولم تُقدّم مُقارِنًا، ستُقذف استثناء ClassCastException عند أول put في وقت التشغيل.
LinkedHashMap — مرتّب حسب الإدراج
يغلّف LinkedHashMap<K, V> جدول تجزئة عاديًا بقائمة مترابطة مضاعفة تمرّ عبر كل إدخال بحسب ترتيب إدراجه. عمليات البحث لا تزال O(1) — تمامًا كـ HashMap — لكن التكرار يعكس الترتيب الذي أُضيفت به المفاتيح أولًا.
وضع الوصول — بناء ذاكرة تخزين LRU
يوجد شكل ثانٍ للمُنشئ: new LinkedHashMap<>(initialCapacity, loadFactor, true). المعامل الثالث يُحوّل الخريطة من ترتيب الإدراج إلى ترتيب الوصول: كل get أو put ينقل الإدخال المُصلَح إلى ذيل القائمة المترابطة. بالتزامن مع تجاوز removeEldestEntry تحصل على ذاكرة تخزين مؤقت بسيطة من نوع LRU (الأقل استخدامًا مؤخرًا) في نحو عشرة أسطر:
Collections.synchronizedMap أو استخدم مكتبة متخصصة.
الاختيار بين تطبيقات الخريطة الثلاثة
- HashMap — الأسرع (O(1) مُخفَّف)، لا ضمان للترتيب. استخدمها حين لا يهمّك الترتيب.
- LinkedHashMap — بحث O(1)، تحفظ ترتيب الإدراج (أو الوصول). استخدمها لتكرار يمكن التنبّؤ به، أو ترتيب تسلسل JSON، أو ذاكرات LRU.
- TreeMap — عمليات O(log n)، مرتّبة دائمًا. استخدمها حين تحتاج استعلامات نطاق أو دوال تنقّل أو ناتج مرتّب مضمون.
مقارنة سريعة
Map<K, V> إلا إن احتجت تحديدًا دوال NavigableMap. هذا يُبقي كودك مرنًا — تستطيع تبديل التطبيق دون لمس مواقع الاستدعاء.
الخلاصة
يحتفظ TreeMap بالمفاتيح مرتّبة (ترتيب طبيعي أو Comparator مخصّص) على حساب عمليات O(log n)، ويضيف دوال تنقّل قوية كـ floorKey وceilingKey وsubMap. أما LinkedHashMap فيحافظ على ترتيب الإدراج (أو ترتيب الوصول عند تفعيل ذلك الخيار) بسرعة O(1) — مما يجعله مثاليًا للتكرار المتوقّع وذاكرات LRU. اختر بناءً على ما إذا كنت تحتاج تنقّلًا مرتّبًا، أو ترتيب إدراج، أو أقصى سرعة.