سؤال

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

من الوكالة، ويمكن أن أضع أيضا طرق المقارنة لفرز مجموعات من الأحجام المتساوية، ولكن استخدام الفرز لن يستفيد من ذلك، وليس هناك حقا طريقة مفيدة + بديهية لمقارنة مجموعات متساوية الحجم (على الأقل ، في حالتي الخاصة)، لذلك يبدو مثل النفايات.

هل تبدو حالة عدم التناقض مثل مشكلة؟

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

المحلول

كما كتب chssply76 في تعليق، يمكنك استخدام HASHCODE لتحديد مكالمة المقارنة في الحالة التي يكون فيها مجموعتان بنفس الحجم ولكنها ليست متساوية. هذا يعمل بشكل جيد، إلا في حالة نادرة حيث يكون لديك مجموعتين بنفس الحجم، ليسا متساوين، ولكن لديهم نفس الحشو. من المسلم به أن فرص حدوث ذلك صغيرة جدا، لكنه يمكن تصوره. إذا كنت تريد أن تكون حذرا حقا، بدلا من Hashcode، استخدم System.Identityhashcode بدلا من ذلك. يجب أن يوفر لك هذا رقما فريدا لكل مجموعة، ويجب ألا تحصل على التصادمات.

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

كود مزيف:

if (a.equals(b)) {
    return 0;
} else if (a.size() > b.size()) {
    return 1;
} else if (b.size() > a.size()) {
    return -1;
} else {
    return System.identityHashCode(a) > System.identityHashCode(b) ? 1 : -1;
}

نصائح أخرى

SortedSet واجهة تمتد الأساسية Set وبالتالي يجب أن تتفق مع العقد الموضح في Set تخصيص.

الطريقة الممكنة الوحيدة لتحقيق ذلك هو الحصول على عنصرك equal() سلوك الطريقة تكون متسقة مع Comparator - سبب ذلك هو هذا الأساسية Set يعمل بناء على المساواة في حين SortedSet يعمل بناء على المقارنة.

علي سبيل المثال، add() الطريقة المحددة في واجهة المجموعة الأساسية تحدد أنه لا يمكنك إضافة عنصر إلى المجموعة إذا كان هناك عنصر بالفعل equal() طريقة ستعود صحيحة مع هذا العنصر الجديد كوسيطة. نحن سوف، SortedSet لا تستخدم equal(), ويستخدم ذلك compareTo(). وبعد لذلك إذا كان لديك compareTo() عائدات false سيتم إضافة عنصرك حتى لو equals() كانت للعودة true, ، وبالتالي كسر Set عقد.

لا شيء من هذا هو عملي مشكلة في حد ذاتها. SortedSet السلوك هو دائما متسقة، حتى لو compare() ضد equals() غير صحيح.

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

لا يوجد أي شرط، إما (في Javadoc) أو ضمني، أن Comparator أن تكون متسقة مع تنفيذ كائن boolean equals(Object).

لاحظ أن Comparable و Comparator نكون واجهات متميزة بأغراض مختلفة. Comparable يستخدم لتحديد أمر "طبيعي" لفئة. في هذا السياق، ستكون فكرة سيئة equals و compateTo أن تكون غير متناسقة. على النقيض من ذلك Comparator يستخدم عندما تريد استخدام طلب مختلف للترتيب الطبيعي للفئة.

تحرير: إليك الفقرة كاملة من Javadoc for SortEded.

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

لقد أبرزت الجملة النهائية. النقطة المهمة هي أن مثل هذه المجموعة سوف تعمل كما تتوقع على الأرجح، ولكن سلوك بعض العمليات لن تطابق بالضبط Set المواصفات ... لأن المواصفة تعرف سلوكهم من حيث equals طريقة.

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

ومع ذلك، ليس من الواضح لي أن المقارنة للمجموعات التي تبدو فقط في مجموعات "الحجم" ستعمل ... من منظور دلالي. أعني، هل تريد حقا أن تقول أن جميع المجموعات مع (قل) 2 عناصر متساوون؟ هذا يعني أن مجموعة الخاص بك يمكن أن تحتوي فقط على مجموعة واحدة من أي حجم معين ...

لا يوجد سبب لماذا Comparator يجب إرجاع نفس النتائج كما equals(). وبعد في الواقع، فإن Comparator تم تقديم API ل equals() فقط لا يكفي: إذا كنت ترغب في فرز مجموعة، فيجب أن تعرف ما إذا كانت عنصران أقل أو أكبر.

إنها غريبة بعض الشيء كجزء من API القياسي يكسر العقد المحدد في واجهة SET ويستخدم المقارنة لتحديد المساواة بدلا من الطريقة المستقيمة، ولكن هذا ما هو عليه.

إذا كانت مشكلتك الفعلية هي فرز مجموعة من المجموعات وفقا لحجم مجموعات المكافين، فستكون أفضل مع قائمة، والتي يمكنك فرزها باستخدام مجموعات (القائمة والمقارنة>)؛

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