📝 LinkedHashSet في جافا: الحل السحري للحفاظ على الترتيب!

LinkedHashSet هي مثل HashSet الذكية التي تحفظ مفاتيحها في ذاكرتها! فهي تجمع بين سرعة HashSet وميزة الحفاظ على ترتيب الإدراج (Insertion Order). هيا نتعمق أكثر.


🔍 ما هو الـ LinkedHashSet؟

LinkedHashSet هي فئة في جافا تنتمي لحزمة java.util. وهي:

  1. مجموعة (Collection) 📦: تخزن مجموعة من العناصر (كائنات).
  2. لا تسمح بالتكرار 🚫: مثل HashSet، كل عنصر فريد داخل LinkedHashSet.
  3. تحفظ ترتيب الإدراج 📅: تحفظ الترتيب الذي أضفت به العناصر. عندما تتجول في عناصرها (باستخدام for-each loop أو Iterator)، ستحصل عليها بنفس الترتيب الذي أضفتها به.
  4. تستخدم جدول التجزئة (Hash Table) مع قائمة مرتبطة (Linked List) ⛓️: هذه هي التقنية السحرية! داخلياً، تستخدم HashSet للبحث السريع، وتستخدم قائمة مرتبطة ثنائية الاتجاه لتسجيل ترتيب العناصر.

ببساطة: LinkedHashSet = HashSet + ترتيب الإدراج.


⚙️ كيفية إنشاء LinkedHashSet

إنشاء LinkedHashSet مشابه جداً لإنشاء HashSet. نحتاج أولاً لاستيراد الحزمة.

import java.util.LinkedHashSet;

public class Main {
    public static void main(String[] args) {
        // 1. إنشاء LinkedHashSet فارغة (لنوع عام)
        LinkedHashSet<String> daysOfWeek = new LinkedHashSet<>();

        // 2. إنشاء LinkedHashSet من مجموعة موجودة (مثل List)
        // سنتعلم هذا لاحقاً عندما ندرس تحويل المجموعات

        // 3. تحديد السعة الأولية (Initial Capacity)
        LinkedHashSet<Integer> numbers = new LinkedHashSet<>(20);
    }
}

✨ الخصائص الرئيسية لـ LinkedHashSet

دعنا نلخص أهم ما يميز LinkedHashSet:

  • ترتيب الإدراج: أكبر ميزة! تحفظ العناصر بالترتيب الذي أتيت به.
  • أداء عالي: عمليات الإضافة (add)، الإزالة (remove)، والبحث (contains) تتم في وقت ثابت تقريباً O(1)، مثل HashSet.
  • لا تكرار: تضمن أن كل عنصر فريد.
  • تسمح بقيمة null: يمكنك إضافة عنصر null واحد فقط.

🔧 الطرق الأساسية في LinkedHashSet (مع أمثلة واقعية)

تشارك LinkedHashSet جميع طرق HashSet لأنها HashSet محسنة! لنرى أهمها في عمل.

مثال 1: الإضافة والحفاظ على الترتيب

import java.util.LinkedHashSet;

public class Main {
    public static void main(String[] args) {
        LinkedHashSet<String> shoppingList = new LinkedHashSet<>();
        
        // إضافة عناصر بترتيب معين
        shoppingList.add("Bread");
        shoppingList.add("Milk");
        shoppingList.add("Eggs");
        shoppingList.add("Apple");
        // لنحاول إضافة "حليب" مرة أخرى (مكرر)
        shoppingList.add("Milk");

        System.out.println("Shopping list: " + shoppingList);
        // The output: Shopping list: [Bread, Milk, Eggs, Apple]
        // Note: "Milk" was ignored as a duplicate, and the order is preserved!
    }
}

مثال 2: المقارنة مع HashSet

import java.util.HashSet;
import java.util.LinkedHashSet;

public class Main {
    public static void main(String[] args) {
        HashSet<String> hashSet = new HashSet<>();
        LinkedHashSet<String> linkedHashSet = new LinkedHashSet<>();

        // نضيف نفس العناصر لكليهما
        hashSet.add("One"); linkedHashSet.add("One");
        hashSet.add("Two"); linkedHashSet.add("Two");
        hashSet.add("Three"); linkedHashSet.add("Three");
        hashSet.add("Four"); linkedHashSet.add("Four");

        System.out.println("HashSet: " + hashSet);
        // قد تطبع: [Four, One, Two, Three] (random order)

        System.out.println("LinkedHashSet: " + linkedHashSet);
        // will always print: [One, Two, Three, Four] (insertion order preserved)
    }
}

مثال 3: الحذف والتحقق من الوجود

import java.util.LinkedHashSet;

public class Main {
    public static void main(String[] args) {
        LinkedHashSet<Integer> numbers = new LinkedHashSet<>();
        numbers.add(10);
        numbers.add(20);
        numbers.add(30);
        numbers.add(40);

        System.out.println("قبل الحذف: " + numbers); // [10, 20, 30, 40]

        // حذف عنصر محدد
        numbers.remove(20);
        System.out.println("بعد حذف 20: " + numbers); // [10, 30, 40]

        // التحقق من وجود عنصر
        if (numbers.contains(30)) {
            System.out.println("العنصر 30 موجود في المجموعة!");
        }

        // معرفة الحجم
        System.out.println("عدد العناصر: " + numbers.size()); // 3
    }
}

⚖️ متى نستخدم LinkedHashSet؟

استخدم LinkedHashSet عندما:

  • تريد منع تكرار العناصر و تحتاج للحفاظ على ترتيب إضافتها.
  • تريد أداءً قريباً من O(1) للعمليات الأساسية ولا تمانع استهلاك ذاكرة إضافي بسيط (للقائمة المرتبطة الداخلية).

مثال: تخزين تاريخ زيارة المستخدمين لصفحة معينة، حيث كل مستخدم يجب أن يظهر مرة واحدة، ونريد معرفة من زار أولاً ومن زار آخراً.


📚 ملخص الدرس

  • LinkedHashSet هي مجموعة في جافا تمنع التكرار وتحفظ ترتيب إدراج العناصر. 📅
  • هي HashSet محسنة، حيث تضيف قائمة مرتبطة داخلياً لتسجيل الترتيب. ⛓️
  • أداؤها سريع جداً (O(1)) في العمليات الأساسية.
  • نستخدمها عندما يكون الترتيب مهماً بجانب تفرد العناصر.
  • طرقها (add, remove, contains, size) مطابقة تماماً لطرق HashSet.