أدوات Collections المساعدة والمقارنات
أدوات Collections المساعدة والمقارنات
تُعدّ كلاس java.util.Collections مجموعةً من الدوال الثابتة (static) التي تعمل على أنواع List وSet وMap. تتولّى هذه الدوال الترتيب والبحث والخلط وعدّ التكرارات وتغليف المجموعات في طبقات للقراءة فقط أو الحماية بين الخيوط — كل ذلك دون الحاجة إلى كتابة الخوارزمية بنفسك. ستتعلّم في هذا الدرس أيضًا كيف تبني كائنات Comparator قابلة للتسلسل حتى تتمكّن من الترتيب بأي معيار تريد.
الترتيب باستخدام Collections.sort
أبسط استخدام لكلاس الأدوات المساعدة هو ترتيب List تنفّذ عناصره واجهة Comparable. السلاسل النصية والأعداد تنفّذ هذه الواجهة بالفعل، لذا يكفي سطر واحد:
تعتمد Collections.sort داخليًا على List.sort، التي تستخدم خوارزمية دمج مستقرة (TimSort). كلمة مستقرة تعني أن العناصر المتساوية تحتفظ بترتيبها الأصلي النسبي — وهذا مهم حين ترتّب بحقل واحد ثم سبق لك الترتيب بحقل آخر.
list.sort(comparator) هو الأسلوب المعتاد — بنفس الكفاءة ويُقرأ بشكل أوضح. أما Collections.sort فهو أقدم وستراه كثيرًا في الكود الذي ستصونه.
العكس والخلط
Collections.reverse تعكس ترتيب القائمة في مكانها. أما Collections.shuffle فتعشوائه، مع إمكانية تمرير Random ذات بذرة محددة لإعادة إنتاج نفس الترتيب:
الطبقات غير القابلة للتعديل والمُزامَنة
أحيانًا تريد مشاركة مجموعة مع كود آخر مع منعه من تعديلها. Collections.unmodifiableList (وما يقابلها لـ Set وMap) تغلّف المجموعة الأصلية في طبقة تُلقي UnsupportedOperationException عند أي محاولة كتابة:
mutable أعلاه، ستعكسه readOnly. للحصول على لقطة غير قابلة للتعديل حقًا، استخدم List.copyOf(mutable) (Java 10+).
Collections.synchronizedList تغلّف القائمة بحيث يكون كل استدعاء لأي دالة آمنًا للخيوط (thread-safe) على حدة. لمتطلبات التزامن الأكثر تعقيدًا استخدم CopyOnWriteArrayList أو ConcurrentHashMap بدلًا من ذلك — لكن الطبقات المُزامَنة خيار سريع حين تحتاج أمانًا أساسيًا فقط.
دوال أدوات مفيدة أخرى
Collections.min(coll)/Collections.max(coll)— إيجاد أصغر أو أكبر عنصر.Collections.frequency(coll, obj)— عدّ كم مرة يظهرobj.Collections.nCopies(n, obj)— إنشاء قائمة غير قابلة للتعديل بـnنسخة منobj(مفيد للحشو أو القيم الافتراضية).Collections.disjoint(c1, c2)— تُعيدtrueإذا لم تتشارك المجموعتان أي عنصر.Collections.swap(list, i, j)— تبديل العنصرين عند موضعين.
بناء المقارنات (Comparators)
حين لا تنفّذ العناصر واجهة Comparable، أو تريد ترتيبًا مختلفًا، تمرّر Comparator. الدالة المصنعية Comparator.comparing تنشئ مقارنًا من دالة استخراج مفتاح:
تسلسل المقارنات
الترتيب الحقيقي غالبًا يحتاج مفتاحًا رئيسيًا ثم مفتاحًا لحل التعادل. توفّر Comparator الدالة thenComparing لهذا الغرض تمامًا:
عكس المقارنات ومعالجة القيم الفارغة
استدعِ .reversed() على أي مقارن لقلب ترتيبه دون إعادة كتابة دالة استخراج المفتاح:
إذا كان المفتاح قد يكون null، غلّف المقارن بـ Comparator.nullsFirst أو Comparator.nullsLast:
Comparator إلى ثابت static final. يجعل ذلك الاختبارات سهلة ويتجنب الأخطاء الدقيقة الناتجة عن بناء المقارن بشكل مختلف في كل مرة.
مثال شامل
إليك مثالًا واقعيًا يجمع بين كلاس الأدوات المساعدة ومقارن مُسلسَل:
الخلاصة
يمنحك كلاس Collections المساعد خوارزميات جاهزة للإنتاج (ترتيب، عكس، خلط، minimum/maximum، تكرار، طبقات للقراءة فقط والحماية بين الخيوط) باستيراد واحد. وتتيح لك واجهة Comparator التعبير عن أي معيار ترتيب بكود مقروء وقابل للتركيب — بتسلسل thenComparing وreversed والمُغلِّفات الآمنة من القيم الفارغة بدلًا من كتابة كتل if متداخلة. يُكمل هذان الأمران معًا صندوق أدوات إطار Collections الذي بنيته عبر هذا الدرس.