سؤال

على حد علمي ، أشياء مثل SortedMap أو SortedSet, ، استعمال compareTo (عوضا عن equals) على Comparable<?> أنواع للتحقق من المساواة (contains, containsKey).

ولكن ماذا لو كانت أنواع معينة قابلة للتصنيف حسب المفهوم ، ولكن ليس مماثلة؟
(رموز التجزئة ، عناوين الذاكرة ، ...)

لا بد لي من إعلان أ Comparator<?> وتجاوز الطريقة int compareTo(T o1, To2). حسنًا ، يمكنني العودة 0 للحالات التي تعتبر متساوية. ولكن ، بالنسبة للحالات غير الثابتة ، ما الذي أعود إليه عندما لا يكون الأمر واضحًا؟

هو نهج استخدام sortedmap أو sortedse على مساواة ولكن (حسب المفهوم) غير قابل للمقارنة أنواع جيدة على أي حال؟

شكرًا لك!

تعديل:
لا أرغب في تخزين الأشياء ، لكن هل سأستخدم الخريطة "المعتادة" والتعيين ، لم أستطع "تجاوز" المساواة في السلوك.

تحرير 2:
لماذا لا أستطيع التجاوز equals(...):
أحتاج إلى تغيير المساواة بين الطبقة الأجنبية. لا يمكنني تعديله.

تحرير 3:
فقط فكر في .NET: لديهم واجهة iequatable التي تعمل على تغيير السلوك المساواة دون لمس السلوك المماثل.

تحرير 4:
لا يمكنني صنع فقط compareTo إرجاع 0 للمتساوية و 1 للحالات غير متساوية؟ ما هي المشكلة الكبيرة؟ لقد قعرت بعض الاختبارات ، يبدو أن Compareto Compareto SortedMap/SortedSet على زوج من الحالات مرة واحدة. نعم ، لن يكون الأمر منطقيًا ، ولكن لماذا يجب أن يكون مشكلتي؟ لا أحتاج إلى الطلب. *أنا فقط بحاجة إلى تغيير المساواة-السلوك. للأسف معظم الناس لا يستطيعون فهم هذا.
ملاحظة: لقد ثبت أن مفهوم العودة 1 للحالات غير المسككة الآن خاطئ.

تحرير 5:
تغيير المساواة-السلوك من الطبقات الأجنبية هو مفهوم سيء؟ بالتأكيد؟ لا أعتقد ذلك: لماذا إذن يُسمح لي بتغيير المقارنة بين السلوك من الطبقات الأجنبية استخدام Comparator?

تحرير 6:
شكرا ل Mark Peters و waxwing لفكرة لف نوع المفتاح في فئة مخصصة. بهذه الطريقة ، أنا يستطيع التجاوز يساوي و hashcode ، وبالتالي تغيير المساواة السلوكية.

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

المحلول

فكر في لف صفك الأجنبي داخلك بدلاً من ذلك.

public class Foreign {
  // undesired equals() and hashCode() implementation
}


public class ForeignWrapper {
   private Foreign foreign;

   public ForeignWrapper(Foreign foreign) {
      this.foreign = foreign;
   }

   public void equals() {
       // your equals implementation, using fields from foreign
   }

   public int hashCode() {
       // your hashCode implementation, using fields from foreign
   }

}

ثم أضف new ForeignWrapper(foreign) إلى hashset القياسية / hashmap. لا ينطبق في جميع الحالات ، ولكن ربما في لك.

نصائح أخرى

لا ، يعد استخدام sortedmap أو sortedset على أنواع المساواة ولكن غير المماثلة فكرة مروعة. إذا لم تكن قابلة للمقارنة مع المقارنة ، فيجب عدم استخدامها في مجموعة فرز. يعني الفرز أن هناك طلبًا ، مما يعني أنه يمكنك مقارنة عنصرين لمعرفة ما هو "أقل".

فقط استخدم hashmap/set.

تحرير إلى تحريرك رقم 2

إذا لم تتمكن من تجاوز المساواة بشكل صحيح ، في مكان ما لديك تصميم سيء للغاية. ستحتاج إلى إعطاء مزيد من المعلومات فيما تحاول تحقيقه.

تحرير إلى تحريرك رقم 3

في جافا ، تعديل يساوي لا تغيير السلوك المماثل. لا تحتاج إلى واجهة لإنجاز ذلك.

تحرير إلى تحريرك رقم 4

لا ، لا يمكنك فقط العودة 1 للعناصر غير متساوية !!

تستخدم مجموعات الفرز المقارنة مع تجد عنصرك في المجموعة. الواجهة المماثلة لها متطلبات محددة. الشخص الذي تكسره هو إذا A.compareTo(B) > 0, ثم بالضرورة B.compareTo(A) < 0. أنت تكسر ما سيجعل من المستحيل العثور على عناصر في مجموعة ما بعد الكلمات الخاصة بك.

public static void main(String[] args) throws Exception {
    SortedSet<MyClass> set = new TreeSet<MyClass>();
    MyClass one = new MyClass(1);
    set.add(one);
    set.add(new MyClass(2));
    set.add(new MyClass(3));
    System.out.println(set.contains(one));
}
private static class MyClass implements Comparable<MyClass> {
    private final int data;
    private MyClass(int data) { this.data = data; }
    public int compareTo(MyClass o) { return (data == o.data ? 0 : 1); }
}

يطبع هذا الرمز false, ، من الواضح أن المقارن الخاص بك قد كسر دلالات المجموعة.

يبدو أنك لا تريد/تحتاج إلى فرز العناصر.

في هذه الحالة ، ربما يمكنك استخدام HashMap و HashSet في حين أن؟ لا جدوى من الاستخدام SortedMap و SortedSet إذا لم تكن بحاجة إلى فرزها.

لا أرغب في تخزين الأشياء ، لكن هل سأستخدم الخريطة "المعتادة" والتعيين ، لم أستطع "تجاوز" المساواة في السلوك.

إذا كنت لا ترغب في تخزين عناصرك المصنفة ، فلماذا تستخدم مجموعة مصنفة؟

من أجل الحفاظ على مجموعة مصنفة ، فإن عملية إدراج (عادةً) لها تعقيد O (log n) لوضع العنصر في المكان الصحيح. إذا لم تكن بحاجة إلى الفرز ، فهذا أمر مضيء ، حيث يمكنك استخدام مجموعة قائمة على التجزئة (HashMap ، Hashset) والتي من شأنها أن تمنحك وقت الإدراج O (1).

هل نهج استخدام sortedMap أو sortedset على المساواة ولكن (حسب المفهوم) غير قابلة للمقارنة جيدة على أي حال؟

لا. الهدف من هذه المجموعات هو السماح لك بفرز الكائنات فيها ، إذا لم يكن للكائنات ترتيب فرز طبيعي ، فما الهدف من وضعها في مجموعة مصنفة؟

يجب عليك تجاوز أساليب متساوية () و hashcode () واستخدام فئات الخريطة/المجموعة القياسية بدلاً من ذلك.

إذا كنت بحاجة إلى تجاوز Hashcode ولكن لا يمكنك ذلك ، فأعتقد أنك تبحث في تمديد HashMap أو الكتابة الخاصة بك.

ليس من الواضح ، ولكن قد يكون كل ما تحاول القيام به هو الحصول على مجموعة من شيء ما, ، باستخدام نفس الدلالات من مجموعة/خريطة ، ولكن مع شيء ما هذا لا ينفذ بشكل كاف Object.equals.

في هذه الحالة أقترح عليك فئة فرعية AbstractSet أو AbstractMap والتجاوز AbstractCollection.contains لاستخدام نسختك من متساوين.

هذا ليس شيئًا أوصي به ، لكن سؤالك لا يوضح في الواقع ما تحاول تحقيقه.

نرى http://java.sun.com/javase/6/docs/api/java/util/abstractset.htmlو http://java.sun.com/javase/6/docs/api/java/util/abstractcollection.html#contains(java.lang.object)

إذا لم تكن الذاكرة مشكلة كبيرة فئة فرعية من الفئة الفرعية و Hashset لاتخاذ فئة المساواة

interface Equality<T>//Defines the equality behavior
{
   int hashCode(T t);//Required, always make sure equals = true => same hashCode
   boolean areEqual(T t,Object t2);
}
class EqualWrapper<T>//Wraps object and equality for the HashMap/Set
{
   T object;
   Equality<T> equal;
   int hashCode(){return equal.hashCode(object);}
   boolean equals(Object o){return equal.areEqual(object,o);}

}
class MySet<T>extends AbstractSet<T>
{
   private HashSet<EqualWrapper<T> > internalSet = new HashSet<T>();
   private Equality<T> equal;
   public MySet(Equality<T> et){equal = et;}
   // TODO implement abstract functions to wrapp 
   // objects and forward them to 
   // internalSet  
}

بهذه الطريقة يمكنك تحديد سلوك المساواة الخاص بك. من الغريب أنه مفقود من JRE

لا يمكنك فرز الكائنات إذا كانت غير قابلة للمقارنة ؛ كيف تعرف أي من الكائنين يجب أن يأتي أولاً إذا لم يكن قابلاً للمقارنة؟ لذلك لا توجد طريقة لوضع الأشياء التي لا يمكن مقارنتها في أ SortedMap أو SortedSet. (لماذا تريد؟ استخدام نوع مختلف من Map أو Set).

ال equals() تم تعريف الطريقة في Java في الفصل Object, ، وبما تمتد جميع الفصول Object, ، جميع الكائنات لها equals() طريقة. عليك أن تهتم بتجاوز وتنفيذ equals() بشكل صحيح في فصولك إذا كنت تريد أن تكون قادرًا على معرفة ما إذا كان كائنين متساويين.

إذا كنت ترغب في وضع كائنات في مجموعة قائمة على التجزئة (مثل HashMap أو HashSet) يجب عليك أيضًا تجاوز hashCode() ويجب عليك التأكد من ذلك hashCode() و equals() يتم تنفيذها بالطريقة الصحيحة (انظر وثائق تلك الأساليب في الفصل Object للحصول على تفاصيل حول كيفية القيام بذلك).

كما قال آخرون ، إذا لم يكن هناك ترتيب طبيعي ، فإن sortedxxx ليس خيارًا حقًا. ومع ذلك ، على افتراض أنك تريد فقط نوعًا من الطرق الثابتة لإدراج العناصر ، إذا كنت تفكر فقط في الحقول التي تستخدمها في اختبار المساواة ، حيث تشكل هذه "المفتاح الأساسي" ، وتوصل إلى نوع من الترتيب العددي أو الأبجدي من حولهم قد يناسب هدفك.

ما عليك سوى استخدام مقارنة (مخصصة) المقدمة لتنفيذ [SET | MAP] عند إنشائها ...

يميل Javadocs إلى اقتراح هذا: All keys inserted into a sorted map must implement the Comparable interface (or be accepted by the specified comparator).

SortedSet<MyObject> s = new TreeSet<MyObject>(new Comparator<MyObject>() {
    @Override
    public int compare(T o1, T o2) {
        // your very specific, fancy dancy code here
    }
});

http://java.sun.com/javase/6/docs/api/

لست متأكدًا مما إذا كنت أرى وجهة نظرك (أعتقد أنك تحاول حل مشكلة من الاتجاه الخاطئ) ، ولكن إذا كنت تريد فقط أ Set أو Map الذي يحافظ أجل الإدراج, ، ثم استخدام LinkedHashSet أو LinkedHashMap على التوالى.


تحديث: وفقًا لاقتباسك:

أحتاج إلى تغيير المساواة بين الطبقة الأجنبية. لا يمكنني تعديله.

داخل مجموعة/خريطة مصنفة؟ ثم استخدم TreeSet أو TreeMap الذي تبنيه مع العرف Comparator. على سبيل المثال

SortedSet<String> set = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);

(الذي يبني مجموعة من Stringأمر في حالة ترتيب غير حساس).

أنظر أيضا:

لا أرغب في تخزين الأشياء ، لكن هل سأستخدم الخريطة "المعتادة" والتعيين ، لم أستطع "تجاوز" المساواة في السلوك.

أنت تحاول تجاوز طريقة equals () لنوع غير معروف. أنت تفكر في المشكلة متمنياً أن يكون لديك واجهة iequatable. إذا كان يجب عليك استخدام sortedset/sortedMap ، فحصل على مقارنة مثل يذكر ptomli في إجابته.

باستخدام hashmap/hashset بدلاً من ذلك يبدو أن اقتراحًا جيدًا. هل نظرت إلى هؤلاء؟

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