واجهة Predicate ومُدمِجاتها
واجهة Predicate ومُدمِجاتها
الواجهة Predicate<T> هي واجهة وظيفية في حزمة java.util.function تمثّل اختبارًا واحدًا: عند إعطائها قيمة من النوع T، ترجع true أو false. إنّها الطريقة القياسية للتعبير عن شرط منطقي في الـ API الوظيفي لـ Java — تُستخدم كثيرًا في Streams API، وفي توابع المجموعات مثل removeIf، وفي أي API يحتاج إلى مرشّح.
التابع المجرّد الوحيد هو boolean test(T t). كل شيء آخر في Predicate — سواء كان and أو or أو negate أو not — هو تابع default أو static يتيح لك بناء شروط مركّبة دون كتابة كتل if متداخلة.
لماذا تهمّنا المسندات القابلة للتركيب؟
تخيّل أنّك تريد تصفية قائمة مستخدمين. بدون التركيب ستكتب إمّا تعبيرًا lambda ضخمًا يفعل كل شيء، أو حلقات for متعددة. بالتركيب تعرّف مسندات صغيرة مُسمّاة وتربطها معًا — كل جزء قابل للاختبار بمفرده، والنتيجة المركّبة تُقرأ كجملة مفهومة.
negate — عكس النتيجة
يرجع negate() Predicate جديدًا هو النفي المنطقي للأصل.
يوجد أيضًا مساعد ثابت هو Predicate.not(predicate) أُضيف في Java 11. إنّه مفيد جدًا داخل سلاسل التوابع حيث قد يستلزم استدعاء .negate() أقواسًا إضافية:
and — يجب أن يتحقّق كلا الشرطين
يرجع and(other) Predicate جديدًا يعمل بالدارة القصيرة: إذا أرجع المسند الأول false فلن يُقيَّم الثاني — تمامًا مثل عامل &&.
and عند أول نتيجة false، ويتوقف or عند أول نتيجة true. هذا يعكس تمامًا عاملَي && و|| في Java — الترتيب مهم إذا كان أحد المسندات يُنتج تأثيرًا جانبيًا أو يستهلك وقتًا في الحساب.
or — يكفي تحقّق أحد الشرطين
يرجع or(other) مسندًا يكون صحيحًا متى كان أحد الطرفين صحيحًا.
تركيب الثلاثة معًا
تظهر القوة الحقيقية عند سلسلة المُدمِجات المتعددة. إليك سيناريو تصفية واقعي لقائمة أسعار منتجات:
atLeastFive يجعل السلسلة تشرح نفسها. تجنّب كتابة تعبير lambda واحد متداخل بعمق — يصعب قراءته ولا يمكن إعادة استخدامه.
استخدام Predicate مع removeIf
Collection.removeIf(Predicate) تابع مريح يحذف كل عنصر يُحقّق المسند المُعطى. يقبل أي Predicate<T> بما في ذلك المركّبة منها:
removeIf آمن — صُمِّم للحذف في مكانه. أمّا stream().filter(...) فلا يُعدّل القائمة الأصلية بل ينتج stream جديدًا. اعرف أيّ السلوكَين تحتاجه قبل الاختيار بينهما.
الخلاصة
تحوّل Predicate<T> الشرط المنطقي إلى كيان من الدرجة الأولى. عملياتها الأربع الرئيسية هي:
test(t)— تقييم الشرط.negate()/Predicate.not(...)— النفي المنطقي.and(other)— الضرب المنطقي مع الدارة القصيرة.or(other)— الجمع المنطقي مع الدارة القصيرة.
بناء مرشّحات معقّدة من مسندات صغيرة مُسمّاة هو أسلوب Java 8+ الاحترافي — قابل للتركيب، سهل القراءة، وسهل الاختبار. ستلتقي بهذا النمط كثيرًا حين نصل إلى درس Streams.