Comparable ve Comparator ne zaman kullanılır?


108

Bir alanda sıralamam gereken nesnelerin bir listesi var, örneğin Puan. Fazla düşünmeden Comparator'ı uygulayan, görevi yerine getiren ve işe yarayan yeni bir sınıf yazdım.

Şimdi geriye dönüp baktığımda, Comparator'ı uygulayan yeni bir sınıf oluşturmak yerine sınıfımın Comparable uygulamasını benimsemem gerekip gerekmediğini merak ediyorum. Puan, nesnelerin sıralanacağı tek alandır.

  1. Bir uygulama olarak kabul edilebilir ne yaptım?

  2. Doğru yaklaşım "Önce sınıfın Karşılaştırılabilir (doğal sıralama için) uygulamasını sağlayın ve alternatif bir alan karşılaştırması gerekiyorsa, Karşılaştırıcıyı uygulayan yeni bir sınıf oluşturun" mu?

  3. Yukarıdaki (2) doğruysa, bu, Comparator'ın ancak sınıf Comparable'ı uyguladıktan sonra uygulanması gerektiği anlamına mı gelir? (Orijinal sınıfa sahip olduğumu varsayarsak).

Yanıtlar:


80

Sınıfı sınıflandırmanın açık ve doğal yolu buysa, bir nesnenin Comparable'ı uygulaması gerektiğini söyleyebilirim ve herhangi birinin sınıfı ayırması gerekir, genellikle bunu bu şekilde yapmak ister.

Bununla birlikte, sıralama sınıfın alışılmadık bir kullanımıysa veya sıralama yalnızca belirli bir kullanım durumu için mantıklıysa, Karşılaştırıcı daha iyi bir seçenektir.

Başka bir deyişle, sınıf adı verildiğinde, bir karşılaştırmanın nasıl sıralandığı açık mı, yoksa javadoc'u okumaya mı başvurmanız gerekiyor? İkincisi ise, olasılıklar, gelecekteki her sıralama kullanım durumu bir karşılaştırıcı gerektirecektir, bu noktada karşılaştırılabilirin uygulanması, sınıfın kullanıcılarını hızlandırmaz, yavaşlatabilir.


Lütfen hızlı bir örnek verebilir misiniz?
rgamber

bu iyi bir örnek olabilir: gist.github.com/yclian/2627608 ComparableVersion kullanan Version sınıfı var. Sürüm - nesne olduğu varsayılan fabrika yöntemlerini sağlar (statik yöntemler olmadan) - bir başkasıyla karşılaştırılabilen bir sürüm sağlar. Sorumluluklar ayrılmıştır.
ses


Muhabir aynı Karşılaştırılabilir ile yapılabilir zaman neden Karşılaştırıcısı kullanın sordu, ben :( dilsiz oldu
Aadam

@aLearner bağlantısı öldü
G.Brown

127

Söz konusu nesnenin varsayılan (doğal) bir sıralama davranışını Comparabletanımlamak istiyorsanız kullanın , bunun için nesnenin teknik veya doğal (veritabanı?) Bir tanımlayıcısını kullanmak yaygın bir uygulamadır.

Kontrol edilebilir harici bir sıralama davranışı Comparatortanımlamak istiyorsanız kullanın , bu, varsayılan sıralama davranışını geçersiz kılabilir.


3
Bu teknik bir açıklama ve geldikleri kadar doğru, ancak en iyi uygulamalar hakkında gerçekten hiçbir şey söylemiyor.
extraneon

40
her birinin ne zaman kullanılacağını söylüyor - bu bir en iyi uygulama değilse, nedir?
Bozho

1
"Uygulama Comparable, doğal düzeni tanımladığım anlamına mı geliyor?" , bu bana aradığım cevabı verdi. Teşekkürler :)
Somjit

61

Kullanım Comparable:

  • nesne sizin kontrolünüzde ise.
  • Karşılaştırma davranışı ana karşılaştırma davranışı ise.

Kullanım Comparator:

  • nesne kontrolünüzün dışındaysa ve bunları uygulayamazsanız Comparable .
  • davranışı varsayılandan (tarafından belirtilen Comparable) farklı bir davranışla karşılaştırmak istediğinizde .

20

Karşılaştırılabilir -java.lang.Comparable: int compareTo(Object o1)

Karşılaştırılabilir bir nesne, kendisini başka bir nesneyle karşılaştırma yeteneğine sahiptir. Örneklerini karşılaştırabilmek için sınıfın kendisi java.lang.Comparable arayüzünü uygulamalıdır.

  • Mevcut nesneyi sağlanan nesne ile karşılaştırabilir.
  • Bunu kullanarak only one sort sequence, örneklerin özelliklerine göre uygulayabiliriz . EX:Person.id
  • String, Wrapper sınıfları, Date, Calendar gibi Önceden Tanımlanmış Sınıflardan bazıları, Karşılaştırılabilir arayüz uygulamıştır.

Karşılaştırıcı -java.util.Comparator: int compare(Object o1, Object o2)

Karşılaştırma nesnesi, iki farklı nesneyi karşılaştırabilir. Sınıf, örneklerini değil, başka bir sınıfın örneklerini karşılaştırıyor. Bu karşılaştırıcı sınıf, java.util.Comparator arayüzünü uygulamalıdır.

  • Aynı Türdeki herhangi iki Nesneyi karşılaştırabilir.
  • Bunu kullanarak many sort sequence, örneklerin özelliklerine göre her birini uygulayabilir ve adlandırabiliriz. EX:Person.id, Person.name, Person.age
  • Özelleştirilmiş sıralama için Önceden tanımlanmış sınıflarımıza Karşılaştırıcı arabirimi uygulayabiliriz.

Misal:

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)
    }
}
  • Özelleştirilmiş sıralama için karşılaştırıcı @compare (o1, o2) için diğer senaryolar için gidiyoruz, karşılaştırılabilir @compareTo (o1) için gidiyoruz, eğer birden fazla alanı sıralamak istiyorsak, o zaman karşılaştırıcı kullanıyoruz.

İçin Java 8 Lambda: Karşılaştırıcı görevime geri gelir.


10

Aynı sınıftaki örnekleri karşılaştırırken karşılaştırılabilir kullanılmalıdır.

Karşılaştırıcı, farklı sınıfların örneklerini karşılaştırmak için kullanılabilir.

Karşılaştırılabilir, nesneleri için doğal bir sıralama tanımlaması gereken sınıf tarafından uygulanır. String gibi, Comparable'ı uygular.

Kişi farklı bir sıralama düzeni isterse, karşılaştırıcıyı uygulayabilir ve iki örneği karşılaştırmak için kendi yolunu tanımlayabilir.


10

Nesnelerin sıralanmasının doğal sıraya dayalı olması gerekiyorsa, Comparable'ı kullanın, ancak sıralamanızın farklı nesnelerin niteliklerine göre yapılması gerekiyorsa, Java'da Comparator'ı kullanın.

Karşılaştırılabilir ve Karşılaştırıcı arasındaki temel farklar:

+------------------------------------------------------------------------------------+
¦               Comparable                ¦                Comparator                ¦
¦-----------------------------------------+------------------------------------------¦
¦ java.lang.Comparable                    ¦ java.util.Comparator                     ¦
¦-----------------------------------------+------------------------------------------¦
¦ int objOne.compareTo(objTwo)            ¦ int compare(objOne, objTwo)              ¦
¦-----------------------------------------+------------------------------------------¦
¦ Negative, if objOne < objTwo            ¦ Same as Comparable                       ¦
¦ Zero,  if objOne == objTwo              ¦                                          ¦
¦ Positive,  if objOne > objTwo           ¦                                          ¦
¦-----------------------------------------+------------------------------------------¦
¦ You must modify the class whose         ¦ You build a class separate from to sort. ¦
¦ instances you want to sort.             ¦ the class whose instances you want       ¦
¦-----------------------------------------+------------------------------------------¦
¦ Only one sort sequence 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, Calendar ¦ instances of third-party classes.        ¦
+------------------------------------------------------------------------------------+

9

Comparator, karşılaştırılabilir her şeyi ve daha fazlasını yapar.

| | 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

Karşılaştırıcıları anonim sınıflar olarak kullanmak için en iyi yaklaşımı şu şekilde buldum:

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());
        }
    });
}

Sıralamayı planladığınız sınıfın içinde bu tür yöntemlerin birden çok sürümünü oluşturabilirsiniz. Böylece sahip olabilirsiniz:

  • sortAccountsByPriority
  • sortAccountsByType
  • sortAccountsByPriorityAndType

    vb...

Artık bu sıralama yöntemlerini her yerde kullanabilir ve kodu yeniden kullanabilirsiniz. Bu bana karşılaştırılabilir olan her şeyi ve daha fazlasını veriyor ... bu yüzden karşılaştırılabilir kullanmak için hiçbir neden görmüyorum.


8

Şöyle söylerdim:

  • karşılaştırma sezgiselse, o zaman kesinlikle Karşılaştırılabilir'i uygulayın
  • Karşılaştırmanızın sezgisel olup olmadığı net değilse, daha açık ve dolayısıyla kodu korumak zorunda olan zavallı ruh için daha net olduğundan bir Karşılaştırıcı kullanın
  • Birden fazla sezgisel karşılaştırma mümkünse, karşılaştırılacak sınıftaki bir fabrika yöntemiyle oluşturulmuş bir Karşılaştırıcıyı tercih ederim.
  • karşılaştırma özel amaçlıysa, Karşılaştırıcıyı kullanın

6

Aşağıdaki noktalar, hangi durumlarda Karşılaştırılabilir ve hangi Karşılaştırıcıyı kullanmanız gerektiğine karar vermenize yardımcı olur:

1) Kod Kullanılabilirliği

2) Tek ve Çoklu Sıralama Kriterleri

3) Arays.sort () ve Collection.sort ()

4) SortedMap ve SortedSet'te anahtar olarak

5) Esnekliğe Karşı Daha Fazla Sınıf Sayısı

6) Sınıflar arası karşılaştırmalar

7) Doğal Düzen

Daha ayrıntılı makale için karşılaştırılabilir ne zaman ve ne zaman karşılaştırıcı kullanılmalıdır?


Merak ediyorum neden kimse bu yanıtı desteklemiyor. Bu gerçekten güzel. +1
Diganta

4
  • Sınıfı yazarken yalnızca bir kullanım durumunuz varsa, Comparable'ı kullanın.
  • Yalnızca birden fazla sıralama stratejiniz olduğunda bir Karşılaştırıcı uygulayın.

4

Doğal sıralama sıralamasına ihtiyacınız varsa - Kullanıcı Karşılaştırılabilir EĞER Özel Sıralamaya ihtiyacınız varsa - Karşılaştırıcı Kullanın

Misal:

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

Doğal sıralı Sıralama, kimliğe dayalı olacaktır çünkü benzersiz olacaktır ve özel sıralama sıralaması ad ve departman olacaktır.

Referanslar:
Bir sınıf ne zaman Karşılaştırılabilir ve / veya Karşılaştırıcı olmalıdır? http://javarevisited.blogspot.com/2011/06/comparator-and-comparable-in-java.html


3

Burada da benzer bir soru vardı: Bir sınıf ne zaman Karşılaştırılabilir ve / veya Karşılaştırıcı olmalıdır?

Şunu söyleyebilirim: Doğal bir sıralama gibi bir şey için, örneğin dahili bir kimliğe dayalı olarak Comparable'ı uygulayın

Daha karmaşık bir karşılaştırma algoritmanız varsa, örneğin birden çok alan vb. Varsa, bir Karşılaştırıcı uygulayın.


1
Birden fazla alanda sipariş vermek de aynı derecede iyi olabilir Comparable.
BalusC

Karşılaştırılabilir ve karşılaştırıcı arasındaki fark için, java-journal.blogspot.in/2010/12/…
Öğrenci

2

Karşılaştırılabilir:
Ne zaman sadece homojen öğeleri ve gerekli olan varsayılan doğal sıralama düzenini depolamak istersek, sınıf uygulamasına geçebiliriz comparable arayüzüne .

Karşılaştırıcı:
Homojen ve heterojen öğeleri saklamak istediğimizde ve varsayılan özelleştirilmiş sıralama düzeninde sıralamak istediğimizde, comparatorarayüze gidebiliriz .


0

Benim ihtiyacım tarihe göre sıralamaktı.

Bu yüzden Comparable'ı kullandım ve benim için kolayca çalıştı.

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

Comparable ile ilgili bir kısıtlama, Listeden başka Koleksiyonlar için kullanılamamalarıdır.



0

Bir röportajda, belirli bir sayı aralığını ilk zamandan daha iyi bir şekilde sıralamam istendi. (Sayma sıralaması kullanılmıyor)

Bir nesne üzerinde Comparable arabiriminin uygulanması, örtük sıralama algoritmalarının sıralama öğelerini sıralamak için geçersiz kılınan CompareTo yöntemini kullanmasına izin verir ve bu doğrusal zaman olacaktır.


0

Karşılaştırılabilir, sayısal değerler için sağlanan varsayılan doğal sıralama düzeni ve artan dizeler için alfabetik sıradır. örneğin:

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

Karşılaştırıcı, özel myComparator sınıfında bir karşılaştırma yöntemini geçersiz kılarak uygulanan özel sıralama düzenidir, örneğin:

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]

-1

Çok basit bir yaklaşım, söz konusu varlık sınıfının veritabanında ve daha sonra veritabanı tablosunda varlık sınıfının alanlarından oluşan dizine ihtiyacınız olduğunu varsaymaktır. Yanıt evet ise, karşılaştırılabilir uygulayın ve doğal sıralama düzeni için dizin alanlarını kullanın. Diğer tüm durumlarda karşılaştırıcı kullanın.


-2

Uygulama için ek açıklama kütüphanem Comparableve 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);         
    }  
}

Daha fazla örnek görmek için bağlantıya tıklayın. http://code.google.com/p/compamatic/wiki/CompamaticByExamples

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.