سؤال

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

إذا نظرنا الآن إلى الوراء في هذا ، أتساءل عما إذا كان ينبغي عليّ بدلاً من ذلك أن يكون لديّ فئة قابلة للمقارنة بدلاً من إنشاء فئة جديدة تقوم بتنفيذ المقارنة. النتيجة هي الحقل الوحيد الذي سيتم طلب الكائنات عليه.

  1. ما فعلته مقبول كممارسة؟

  2. هل النهج الصحيح "أولاً يكون للفئة تنفيذ قابلة للمقارنة (للترتيب الطبيعي) وإذا كانت هناك حاجة إلى مقارنة حقل بديلة ، ثم قم بإنشاء فئة جديدة تنفذ المقارنة"؟

  3. إذا كان (2) أعلاه صحيحًا ، فهل هذا يعني أنه يجب على المرء أن ينفذ المقارنة فقط بعد أن يكون للفئة تنفيذ قابلة للمقارنة؟ (على افتراض أنني أملك الفصل الأصلي).

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

المحلول

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

ومع ذلك ، إذا كان الفرز استخدامًا غير عادي للفئة ، أو أن الفرز منطقي فقط لحالة الاستخدام المحددة ، فإن المقارنة هي خيار أفضل.

بعبارة أخرى ، بالنظر إلى اسم الفصل ، هل من الواضح كيف يمكن فرز المقارنة ، أو هل يجب عليك اللجوء إلى قراءة Javadoc؟ إذا كان هذا هو الأخير ، فإن كل حالة استخدام فرز الاستخدام في المستقبل تتطلب مقارنة ، وعندها قد يؤدي تنفيذ قابلة للمقارنة إلى إبطاء مستخدمي الفصل ، وليس تسريعهم.

نصائح أخرى

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

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

يستخدم Comparable:

  • إذا كان الكائن في سيطرتك.
  • إذا كان السلوك المقارنة هو السلوك الرئيسي المقارنة.

يستخدم Comparator :

  • إذا كان الكائن خارج سيطرتك ولا يمكنك جعلها تنفذها Comparable.
  • عندما تريد مقارنة السلوك مختلفًا عن الافتراضي (الذي يتم تحديده بواسطة Comparable) سلوك.

مماثلة - java.lang.Comparable: int compareTo(Object o1)

كائن مماثل قادر على مقارنة نفسه مع كائن آخر. يجب أن يقوم الفصل نفسه بتنفيذ واجهة java.lang.comparable حتى تتمكن من مقارنة مثيلاتها.

  • قادرة على مقارنة الكائن الحالي مع الكائن المقدم.
  • باستخدام هذا يمكننا تنفيذ only one sort sequence بناء على خصائص الحالات. السابق: Person.id
  • قامت بعض الفئات المحددة مسبقًا مثل String و Wrapper Breass و Date و Calendar بتنفيذ واجهة مماثلة.

المقارنة - java.util.Comparator: int compare(Object o1, Object o2)

كائن المقارنة قادر على مقارنة كائنين مختلفين. لا يقارن الفصل حالاته ، ولكن بعض مثيلات الطبقة الأخرى. يجب أن تنفذ فئة المقارنة هذه واجهة java.util.comparator.

  • قادرة على مقارنة أي كائنين من نفس النوع.
  • باستخدام هذا يمكننا تنفيذ many sort sequence وتسمية كل منها ، بناءً على خصائص الحالات. السابق: Person.id, Person.name, Person.age
  • يمكننا تنفيذ واجهة المقارنة على فئاتنا المحددة مسبقًا للفرز المخصص.

مثال:

public class Employee implements Comparable<Employee> {

    private int id;
    private String name;
    private int age;
    private long salary;

    // Many sort sequences can be created with different names.
    public static Comparator<Employee> NameComparator = new Comparator<Employee>() {         
        @Override
        public int compare(Employee e1, Employee e2) {
            return e1.getName().compareTo(e2.getName());
        }
    };
    public static Comparator<Employee> idComparator = new Comparator<Employee>() {       
        @Override
        public int compare(Employee e1, Employee e2) {
            return Integer.valueOf(e1.getId()).compareTo(Integer.valueOf(e2.getId()));
        }
    };

    public Employee() { }
    public Employee(int id, String name, int age, long salary){
        this.id = id;
        this.name = name;
        this.age = age;
        this.salary = salary;
    }
    // setters and getters.

    // Only one sort sequence can be created with in the class.
    @Override
    public int compareTo(Employee e) {
    //return Integer.valueOf(this.id).compareTo(Integer.valueOf(e.id));
    //return Character.toString(this.name.charAt(0)).compareToIgnoreCase(Character.toString(e.name.charAt(0)));
        if (this.id > e.id) {
            return 1;
        }else if(this.id < e.id){
            return -1;
        }else {
            return Character.toString(this.name.charAt(0)).compareToIgnoreCase(Character.toString(e.name.charAt(0)));
        }

    }   

    public static void main(String[] args) {

        Employee e1 = new Employee(5, "Yash", 22, 1000);
        Employee e2 = new Employee(8, "Tharun", 24, 25000);

        List<Employee> list = new ArrayList<Employee>();
        list.add(e1);
        list.add(e2);
        Collections.sort(list); // call @compareTo(o1)
        Collections.sort(list, Employee.nameComparator); // call @compare (o1,o2)
        Collections.sort(list, Employee.idComparator); // call @compare (o1,o2)
    }
}
  • بالنسبة للفرز المخصص ، نذهب للحصول على المقارنة (O1 ، O2) للسيناريوهات الأخرى التي نذهب إليها من أجل ComplipeCompareto (O1) ، مع تغيير الكود إذا أردنا فرز أكثر من حقل ثم نستخدم المقارنة.

إلى عن على Java 8 Lambda: المقارنة الرجوع إلى رسالتي.

يجب استخدام المقارنة عند مقارنة مثيلات نفس الفصل.

يمكن استخدام المقارنة لمقارنة مثيلات الفصول المختلفة.

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

في حالة يريد المرء أمر فرز مختلف ، يمكنه تنفيذ المقارنة وتحديد طريقته الخاصة في مقارنة حالتين.

المقارنة يفعل كل ما يفعله قابلة للمقارنة ، بالإضافة إلى المزيد.

| | Comparable | Comparator ._______________________________________________________________________________ Is used to allow Collections.sort to work | yes | yes Can compare multiple fields | yes | yes Lives inside the class you’re comparing and serves | | as a “default” way to compare | yes | yes Can live outside the class you’re comparing | no | yes Can have multiple instances with different method names | no | yes Input arguments can be a list of | just Object| Any type Can use enums | no | yes

لقد وجدت أفضل طريقة لاستخدام المقارنة كطبقات مجهولة على النحو التالي:

private static void sortAccountsByPriority(List<AccountRecord> accounts) {
    Collections.sort(accounts, new Comparator<AccountRecord>() {

        @Override
        public int compare(AccountRecord a1, AccountRecord a2) {
            return a1.getRank().compareTo(a2.getRank());
        }
    });
}

يمكنك إنشاء إصدارات متعددة من هذه الطرق مباشرة داخل الفصل الذي تخطط لفرزه. لذلك يمكنك الحصول على:

  • SortAccountsbyPriority
  • SortAccountsbytype
  • SortAccountsByPriorityandType

    إلخ...

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

أود أن أقول:

  • إذا كانت المقارنة بديهية ، فعندئذ بكل الوسائل تنفيذ قابلة للمقارنة
  • إذا كان من غير الواضح أن مقارنتك بديهية ، فاستخدم المقارنة لأنه أكثر وضوحًا وبالتالي أكثر وضوحًا للروح الفقيرة التي يتعين عليها الحفاظ على الكود
  • إذا كان هناك أكثر من مقارنة بديهية ممكنة ، فأنا أفضل مقارنًا ، وربما بناء طريقة مصنع في الفصل المراد مقارنته.
  • إذا كانت المقارنة غرضًا خاصًا ، فاستخدم المقارنة

إذا كان فرز الكائنات بحاجة إلى أن يعتمد على الترتيب الطبيعي ، فاستخدم قابلاً للمقارنة بينما إذا كنت بحاجة إلى الفرز على سمات كائنات مختلفة ، فاستخدم المقارنة في Java.

الفرق الرئيسي بين المقارنة والمقارنة:

+------------------------------------------------------------------------------------+
¦               Comparable                ¦                Comparator                ¦
¦-----------------------------------------+------------------------------------------¦
¦ java.lang.Comparable                    ¦ java.util.Comparator                     ¦
¦-----------------------------------------+------------------------------------------¦
¦ int objOne.compareTo(objTwo)            ¦ int compareTo(objOne, objTwo)            ¦
¦-----------------------------------------+------------------------------------------¦
¦ Negative, if objOne < objTwo            ¦ Same as Comparable                       ¦
¦ Zero,  if objOne == objTwo              ¦                                          ¦
¦ Positive,  if objOne > objTwo           ¦                                          ¦
¦-----------------------------------------+------------------------------------------¦
¦ You must modify the clas whose          ¦ You build a class separate from to sort. ¦
¦ instances you want to sort.             ¦ the class whose instances you want       ¦
¦-----------------------------------------+------------------------------------------¦
¦ Only one sort sequemce can be created   ¦ Many sort sequences can be created       ¦
¦-----------------------------------------+------------------------------------------¦
¦ Implemented frequently in the API by:   ¦ Meant to be implemented to sort          ¦
¦ String, Wrapper classes, Date, Calandar ¦ instances of third-party classes.        ¦
+------------------------------------------------------------------------------------+
  • إذا كان لديك في لحظة كتابة الفصل ، فلديك حالة استخدام واحدة فقط من الاستخدام القابلة للمقارنة.
  • فقط عندما يكون لديك أكثر من استراتيجية واحدة لفرز تنفيذ المقارنة.

تساعدك النقاط التالية في اتخاذ قرار يجب أن يستخدم فيه المواقف قابلة للمقارنة وفي أي مقارنة:

1) رمز توافر

2) معايير فرز مفردة مقابل متعددة

3) arays.sort () و collection.sort ()

4) كمفاتيح في sortedMap و sortedset

5) عدد أكبر من الفئات مقابل المرونة

6) مقارنات interclass

7) النظام الطبيعي

لمزيد من المقالة التفصيلية يمكنك الرجوع إليها متى تستخدم قابلة للمقارنة ومتى تستخدم المقارنة

كان هناك سؤال مماثل هنا: متى يجب أن يكون الفصل قابلاً للمقارنة و/أو المقارنة؟

أود أن أقول ما يلي: قم بتنفيذ ما يمكن مقارنته لشيء مثل الطلب الطبيعي ، على سبيل المثال ، بناءً على معرف داخلي

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

إذا كنت بحاجة إلى فرز الطلب الطبيعي - مستخدم قابل للمقارنة إذا كنت بحاجة إلى فرز الطلب المخصص - استخدم المقارنة

مثال:

Class Employee{
private int id;
private String name;
private String department;
}

يعتمد فرز الطلب الطبيعي على المعرف لأنه سيكون فريدًا وسيكون طلب orderin g ، سيكون اسمًا وقسمًا.

الامتناع:
متى يجب أن يكون الفصل قابلاً للمقارنة و/أو المقارنة؟ http://javarevisited.blogspot.com/2011/06/Comparator--comparable-in-java.html

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

المقارنة:
كلما أردنا تخزين عناصر متجانسة وغير متجانسة ونريد الفرز في ترتيب الفرز المخصص الافتراضي ، يمكننا الذهاب إليه comparator واجهه المستخدم.

كانت حاجتي فرزًا على التاريخ.

لذلك ، استخدمت قابلة للمقارنة وعملت بسهولة بالنسبة لي.

public int compareTo(GoogleCalendarBean o) {
    // TODO Auto-generated method stub
    return eventdate.compareTo(o.getEventdate());
}

أحد القيود المماثلة للمقارنة هو أنها لا يمكن استخدامها في مجموعات أخرى غير القائمة.

إذا كنت تملك الفصل أفضل الذهاب مع مماثلة. عمومًا المقارنة يستخدم إذا كنت لا تملك الفصل ولكن عليك استخدامه الأشجار أو تريماب لأنه يمكن تمرير المقارنة كمعلمة في conctructor من Treeset أو treemap. يمكنك معرفة كيفية استخدام المقارنة والمقارنة في http://preciselyconcise.com/java/collections/g_comparator.php

لقد طلب مني فرز مجموعة محددة من الأرقام بشكل أفضل من وقت Nlogn في واحدة من المقابلة. (عدم استخدام فرز العد)

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

قابلة للمقارنة هو ترتيب الفرز الطبيعي الافتراضي المقدم للقيم العددية هو الصعود والسلاسل هي ترتيب أبجدي. على سبيل المثال:

Treeset t=new Treeset();
t.add(2);
t.add(1);
System.out.println(t);//[1,2]

المقارن هو ترتيب الفرز المخصص الذي تم تنفيذه في فئة MyComparator المخصصة من خلال تجاوز طريقة المقارنة لـ EG:

Treeset t=new Treeset(new myComparator());
t.add(55);
t.add(56);
class myComparator implements Comparator{
public int compare(Object o1,Object o2){
//Descending Logic
}
}
System.out.println(t);//[56,55]

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

التعليقات التوضيحية لي للتنفيذ Comparable و Comparator:

public class Person implements Comparable<Person> {         
    private String firstName;  
    private String lastName;         
    private int age;         
    private char gentle;         

    @Override         
    @CompaProperties({ @CompaProperty(property = "lastName"),              
        @CompaProperty(property = "age",  order = Order.DSC) })           
    public int compareTo(Person person) {                 
        return Compamatic.doComparasion(this, person);         
    }  
}

انقر على الرابط لرؤية المزيد من الأمثلة.http://code.google.com/p/compamatic/wiki/CompamaticByExamples

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