0Pricing
Java Academy · درس

EnumMap

خرائط فعّالة مفاتيحها من Enums

EnumMap درس مجاني في Java Academy على CoddyKit. هذا هو الدرس 4 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Java Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Java Academy 4 دروس في المجموع.

ما هو EnumMap؟

إن EnumMap تنفيذ متخصص للواجهة Map، وتكون مفاتيحه ثوابت من نوع تعداد واحد.

وهو داخليًا مدعوم بـ مصفوفة عادية تُفهرس باستخدام الرقم الترتيبي للثابت. وهذا يجعل عمليات البحث والإدراج سريعة للغاية من دون استخدام التجزئة.

import java.util.EnumMap;
import java.util.Map;

public class Main {
    enum Day { MON, TUE, WED }
    public static void main(String[] args) {
        Map<Day, String> plan = new EnumMap<>(Day.class);
        plan.put(Day.MON, "Gym");
        plan.put(Day.WED, "Swim");
        System.out.println(plan);
    }
}

يتطلب الإنشاء الفئة

يجب أن يعرف EnumMap نوع المفتاح مسبقًا، ولذلك يستقبل المُنشئ كائن Class: new EnumMap<>(Day.class).

وبهذه الطريقة يضبط حجم مصفوفتها الداخلية وفق عدد الثوابت.

import java.util.EnumMap;

public class Main {
    enum Priority { LOW, MEDIUM, HIGH }
    public static void main(String[] args) {
        EnumMap<Priority, Integer> counts = new EnumMap<>(Priority.class);
        counts.put(Priority.HIGH, 5);
        System.out.println(counts.get(Priority.HIGH));
    }
}

سرعة مدعومة بالمصفوفات

بما أن المفاتيح تُخزَّن في array[ordinal]، فإن عمليتي get وput هما وصول مباشر إلى المصفوفة، وهو أسرع من التجزئة والتنقل بين الحاويات في HashMap.

لا يحدث تغليف للمفتاح، ولا تُستدعى الدالة hashCode.

import java.util.EnumMap;

public class Main {
    enum Slot { A, B, C, D }
    public static void main(String[] args) {
        EnumMap<Slot, Integer> m = new EnumMap<>(Slot.class);
        for (Slot s : Slot.values()) m.put(s, s.ordinal() * 10);
        System.out.println(m.get(Slot.C));
    }
}

التكرار بترتيب المفاتيح

يكرّر EnumMap الإدخالات وفق الترتيب الطبيعي للمفاتيح، أي ترتيب التصريح عنها.

وهذا يمنحكم مخرجات مستقرة ومتوقعة، بخلاف HashMap.

import java.util.EnumMap;
import java.util.Map;

public class Main {
    enum Phase { PLAN, BUILD, SHIP }
    public static void main(String[] args) {
        Map<Phase, Integer> hours = new EnumMap<>(Phase.class);
        hours.put(Phase.SHIP, 3);
        hours.put(Phase.PLAN, 8);
        hours.put(Phase.BUILD, 20);
        for (Map.Entry<Phase, Integer> e : hours.entrySet()) {
            System.out.println(e.getKey() + " = " + e.getValue());
        }
    }
}

المفاتيح الفارغة ممنوعة

لا يسمح EnumMap بـ المفاتيح الفارغة؛ إذ يؤدي المفتاح الفارغ إلى إطلاق NullPointerException.

أما القيم الفارغة فهي مسموحة، مثلما هو الحال في الخرائط الأخرى.

import java.util.EnumMap;

public class Main {
    enum K { A, B }
    public static void main(String[] args) {
        EnumMap<K, String> m = new EnumMap<>(K.class);
        m.put(K.A, null); // null value is fine
        System.out.println("A -> " + m.get(K.A));
        System.out.println("contains A: " + m.containsKey(K.A));
    }
}

التجميع باستخدام EnumMap

من الاستخدامات الشائعة العد أو التجميع حسب فئة تعداد. وتجعل merge عملية الإحصاء موجزة.

import java.util.EnumMap;
import java.util.List;
import java.util.Map;

public class Main {
    enum Type { FRUIT, VEG, MEAT }
    record Item(String name, Type type) {}
    public static void main(String[] args) {
        List<Item> items = List.of(new Item("apple", Type.FRUIT), new Item("pear", Type.FRUIT), new Item("beef", Type.MEAT));
        Map<Type, Integer> counts = new EnumMap<>(Type.class);
        for (Item i : items) counts.merge(i.type(), 1, Integer::sum);
        System.out.println(counts);
    }
}

getOrDefault و computeIfAbsent

تعمل جميع الدوال الافتراضية القياسية في Map. وتتجنب getOrDefault فحوص القيم الفارغة، بينما تنشئ computeIfAbsent القيم عند الحاجة فقط.

import java.util.ArrayList;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;

public class Main {
    enum Group { A, B }
    public static void main(String[] args) {
        Map<Group, List<String>> m = new EnumMap<>(Group.class);
        m.computeIfAbsent(Group.A, k -> new ArrayList<>()).add("first");
        System.out.println(m);
        System.out.println(m.getOrDefault(Group.B, List.of()));
    }
}

مُنشئ النسخ

يحتوي EnumMap على مُنشئ نسخ يقبل Map أخرى. وإذا كان المصدر هو EnumMap، فيُستدل على نوع المفتاح منه.

import java.util.EnumMap;
import java.util.Map;

public class Main {
    enum K { X, Y }
    public static void main(String[] args) {
        EnumMap<K, Integer> a = new EnumMap<>(K.class);
        a.put(K.X, 1);
        EnumMap<K, Integer> b = new EnumMap<>(a);
        b.put(K.Y, 2);
        System.out.println("copy: " + b);
    }
}

EnumMap مقابل مصفوفات ordinal

قبل ظهور EnumMap، كان الناس يستخدمون مصفوفات أولية تُفهرس باستخدام ordinal(). وهذا أسلوب هش وغير آمن.

يوفر EnumMap سرعة المصفوفات نفسها، مع أمان الأنواع، وأمان حدود الفهرسة، وواجهة Map واضحة.

import java.util.EnumMap;
import java.util.Map;

public class Main {
    enum Season { SPRING, SUMMER, FALL, WINTER }
    public static void main(String[] args) {
        Map<Season, String> mood = new EnumMap<>(Season.class);
        mood.put(Season.SUMMER, "sunny");
        // Safer and clearer than String[] indexed by ordinal
        System.out.println(mood.get(Season.SUMMER));
    }
}

خرائط EnumMap متداخلة

يمكنكم تداخل خرائط EnumMap لنمذجة مصفوفة مفاتيحها تعدادان، مثل جدول انتقالات الحالات.

import java.util.EnumMap;
import java.util.Map;

public class Main {
    enum State { SOLID, LIQUID, GAS }
    enum Transition { MELT, FREEZE }
    public static void main(String[] args) {
        Map<State, Map<Transition, State>> table = new EnumMap<>(State.class);
        Map<Transition, State> solid = new EnumMap<>(Transition.class);
        solid.put(Transition.MELT, State.LIQUID);
        table.put(State.SOLID, solid);
        System.out.println(table.get(State.SOLID).get(Transition.MELT));
    }
}

اختيار النوع المناسب

قاعدة عامة:

  • إذا كانت المفاتيح ثوابت تعداد وتريدون خريطة، فاستخدموا EnumMap.
  • إذا أردتم مجموعة من التعدادات، فاستخدموا EnumSet.
  • إذا كانت المفاتيح كائنات عشوائية، فاستخدموا HashMap.
import java.util.EnumMap;
import java.util.Map;

public class Main {
    enum Level { DEBUG, INFO, WARN, ERROR }
    public static void main(String[] args) {
        Map<Level, Integer> thresholds = new EnumMap<>(Level.class);
        for (Level l : Level.values()) thresholds.put(l, l.ordinal() * 100);
        System.out.println(thresholds);
    }
}

تحقق سريع

اختبروا معرفتكم بـ EnumMap.

مراجعة

تعلّمتم EnumMap:

  • واجهة Map مدعومة بمصفوفة ومفاتيحها ثوابت تعداد.
  • يستقبل المُنشئ Class المفتاح، ولا يُسمح بالمفاتيح الفارغة.
  • يكرّر العناصر بترتيب التصريح.
  • بديل آمن وسريع عن المصفوفات المفهرسة باستخدام ordinal.

لقد أكملتم دورة التعدادات المتقدمة.

import java.util.EnumMap;

public class Main {
    enum K { A }
    public static void main(String[] args) {
        EnumMap<K, String> m = new EnumMap<>(K.class);
        m.put(K.A, "done");
        System.out.println("EnumMap course complete: " + m.get(K.A));
    }
}

الأسئلة الشائعة

هل درس «EnumMap» مجاني؟

نعم — نص درس «EnumMap» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Java Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Java Academy 4 دروس في المجموع.

ماذا ستتعلم في «EnumMap»؟

خرائط فعّالة مفاتيحها من Enums تتمرن على Java Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ Java Academy؟

لا تُشترط خبرة سابقة. Java Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 4 من أصل 4.

كم من الوقت يستغرق درس «EnumMap»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس Java Academy هذا؟

نعم. كل درس في Java Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. Enums مع الحقول والدوال
  2. الدوال المجرّدة في Enums
  3. EnumSet
  4. EnumMap
← العودة إلى Java Academy