البرمجة

تجنب استثناء ConcurrentModificationException

السلوك الذي تشهده هنا يتسبب في إثارة استثناء ConcurrentModificationException، والذي يحدث عندما يتم تعديل مباشرةً على مجموعة بينما يتم تكرارها بطريقة غير مصرح بها. في الواقع، وعلى الرغم من أنك لا تقوم بالتكرار مباشرةً باستخدام حلقة، إلا أن استخدامك للدالة subList() يقوم بإنشاء رابطٍ مع القائمة الأصلية، وبالتالي تعد هذه القائمة فعالةً للتعديل. وعندما تحاول إجراء removeAll() على القائمة الأصلية بعد ذلك، يتم إثارة الاستثناء لأن التعديلات تتم في القائمة أثناء عملية التحويل.

لتجنب هذا السلوك، يمكنك إما استخدام نسخة من القائمة قبل تعديلها أو استخدام الدالة removeIf() بدلاً من removeAll() لإزالة العناصر بناءً على شرط محدد دون إثارة الاستثناء المشار إليه. على سبيل المثال، يمكن تعديل الدالة processDelete() بالشكل التالي:

java
private boolean processDelete(List list) { boolean success = false; if (list.size() > 999) { List subList = new ArrayList<>(list.subList(0, 998)); list.removeIf(subList::contains); // removeIf() تحذف العناصر التي تفي بالشرط المعين success = true; } else { // } return success; }

باستخدام هذا الأسلوب، ستتجنب الاستثناء وستتمكن من إزالة العناصر المطلوبة من القائمة دون مشاكل.

المزيد من المعلومات

بالطبع، دعني أوضح المزيد من المعلومات لتفهم أفضل للمشكلة وكيفية حلها.

عندما تستخدم الدالة subList()، فإنها لا تقوم بإنشاء نسخة جديدة من القائمة، بل تنشئ فقط رابطًا (view) يشير إلى نفس القائمة الأصلية. وهذا يعني أن أي تغيير يتم على القائمة الفرعية سيؤثر مباشرة على القائمة الأصلية.

عندما تقوم بتنفيذ list.removeIf(subList::contains)، فإنك في الواقع تقوم بإزالة العناصر من القائمة الأصلية باستخدام شرط محدد، وهذا لا يؤثر على القائمة الفرعية المشتقة من subList().

بالنسبة للتعليمات البرمجية التي قدمتها، يبدو أن الهدف هو حذف العناصر الأولى من القائمة list إذا كانت حجمها أكبر من 999. إذا كان الهدف هو فقط حذف العناصر من القائمة، فإن استخدام removeIf() يعتبر الحل الأمثل.

لذا، تجنباً لاستثناء ConcurrentModificationException، يمكنك تنفيذ الحلول التالية:

  1. استخدم نسخة جديدة من القائمة قبل تعديلها باستخدام subList() مثلما فعلت بالفعل، ولكن استخدم removeAll() على النسخة المستنسخة بدلاً من القائمة الأصلية.
  2. استخدم removeIf() كما تم شرحه في الرمز البرمجي السابق.

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

زر الذهاب إلى الأعلى