سؤال

أخذني هذا الخطأ بعض الوقت للعثور ...

النظر في هذه الطريقة:

public void foo(Set<Object> set)
{
    Object obj=set.iterator().next();
    set.remove(obj)
}

أحصل على الطريقة مع مجموعة تجزئة غير فارغة، ولكن لن تتم إزالة أي عنصر!

لماذا سيكون ذلك؟

هل كانت مفيدة؟

المحلول

بالنسبة لحضور الحزام، يمكن أن يحدث هذا إذا كان تغييرات Hashcode للكائن بعد إضافة إلى المجموعة. قد تنظر طريقة Hashset.Remove () إلى دلو التجزئة الخاطئ وفشل في العثور عليه.

ربما لن يحدث ذلك إذا فعلت INTERATOR.REMOVE ()، ولكن في أي حال، تخزين الكائنات في Hashset التي يمكن أن تتغير Hashcode هو حادث ينتظر حدوثه (كما اكتشفت).

نصائح أخرى

لغز؟ إذا Object.hashCode, Object.equals أو تم تنفيذ "مجموعة التجزئة" بشكل غير صحيح (انظر على سبيل المثال، java.net.URL - استعمال URI).

أيضا إذا كانت المجموعة (بشكل مباشر أو غير مباشر) تحتوي على نفسها، فمن المحتمل أن يحدث شيء غريب (بالضبط ما هو تنفيذ ومرحلة القمر المعتمدة).

ما هو نوع التنفيذ من المجموعة وما الأشياء الموجودة داخل المجموعة؟

  • إذا كانت الحزينة، فتأكد من أن قيمة طريقة Hashcode () الكائنات لا تزال ثابتة بين set.put(...) و set.remove(...).
  • إذا كانت هذه الأشجار، فتأكد من عدم إجراء تعديلات على الكائن الذي يؤثر على المقارنة في المجموعة أو الكائن compareTo طريقة.

في كلتا الحالتين، رمز بين set.put(...) و set.remove(...) ينتهك العقد المحدد من قبل تنفيذ الطبقة المعنية. كقاعدة عامة من الإبهام، من الجيد استخدام كائنات ثابتة مثل المحتوى المحتوى (وكخفية خريطة). بطبيعتها الطبيعية، لا يمكن تغيير هذه الكائنات أثناء تخزينها داخل مجموعة.

إذا كنت تستخدم بعض التطبيقات الأخرى، تحقق من Javadoc لعقدها؛ ولكن عادة أيضا equals أو hashCode يجب أن تبقى كما هي أثناء وجود الكائن في المجموعة.

ما وراء المفقودين "؛" بعد set.remove(obj), ، يمكن أن يحدث في ثلاث حالات (نقلت عن جافادوك).

ClassCastException - if the type of the specified element is incompatible with this set (optional).
NullPointerException - if the specified element is null and this set does not support null elements (optional). 
UnsupportedOperationException - if the remove method is not supported by this set.

يمكنك أيضا تجربة:

public void foo(Set<Object> set)
{
    Object obj=set.iterator().next();
    iterator.remove();
}

هل يجب أن تكون:

public void foo(Set<Object> set)
{
    Iterator i = set.iterator();
    i.next();
    i.remove();
}

?

الخطأ يمكن أن يكون شيئا ما يجب القيام به مع:

إزالة الفراغ العامة ()

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

(مرجع)

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

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top