Quando usare Comparable e Comparator

Ho una lista di oggetti che devo ordinare su un campo, ad esempio Score. Senza pensarci troppo ho scritto una nuova class che implementa Comparator, che fa il compito e funziona.

Ora, ripensandoci, mi chiedo se dovrei avere invece il mio strumento di class Comparable invece di creare una nuova class che implementa Comparator. Il punteggio è l’unico campo su cui gli oggetti saranno ordinati.

  1. Quello che ho fatto è accettabile come pratica?

  2. È l’approccio giusto “Per prima cosa l’implementazione della class Comparable (per l’ordinamento naturale) e se è richiesto un confronto di campo alternativo, quindi creare una nuova class che implementi Comparator”?

  3. Se (2) sopra è vero, vuol dire che si dovrebbe implementare Comparator solo dopo aver implementato la class Comparable? (Supponendo che possiedo la class originale).

Direi che un object dovrebbe implementare Comparable se questo è il modo naturale per ordinare la class, e chiunque dovrebbe ordinare la class in generale vorrebbe farlo in quel modo.

Se, tuttavia, l’ordinamento era un uso insolito della class, o l’ordinamento ha senso solo per uno specifico caso d’uso, allora un Comparatore è un’opzione migliore.

In altre parole, dato il nome della class, è chiaro come sarebbe comparabile un paragonabile, o devi ricorrere alla lettura del javadoc? Se è quest’ultimo, le probabilità sono che ogni futuro caso di ordinamento richiederebbe un comparatore, a quel punto l’implementazione di comparabili potrebbe rallentare gli utenti della class, non accelerarli.

Usa Comparable se si desidera definire un comportamento di ordinamento (naturale) predefinito dell’object in questione, una pratica comune è quella di utilizzare un identificatore tecnico o naturale (database?) Dell’object per questo.

Usa Comparator se si desidera definire un comportamento di ordinamento controllabile esterno , questo può ignorare il comportamento di ordinamento predefinito.

Usa Comparable :

  • se l’object è nel tuo controllo.
  • se il comportamento di confronto è il comportamento di confronto principale.

Usa Comparator :

  • se l’object è fuori dal tuo controllo e non puoi renderlo implementabile Comparable .
  • quando si desidera confrontare un comportamento diverso dal comportamento predefinito (che è specificato da Comparable ).

Comparabilejava.lang.Comparable: int compareTo(Object o1)

Un object comparabile è in grado di confrontarsi con un altro object. La class stessa deve implementare l’interfaccia java.lang.Comparable per poter confrontare le sue istanze.

  • Capace di confrontare l’object corrente con l’object fornito.
  • Usando questo possiamo implementare only one sort sequence basata sulle proprietà delle istanze. EX: Person.id
  • Alcune delle classi predefinite come le classi String, Wrapper, Date, Calendar hanno implementato l’interfaccia Comparable.

Comparatorejava.util.Comparator: int compare(Object o1, Object o2)

Un object comparatore è in grado di confrontare due oggetti diversi. La class non sta confrontando le sue istanze, ma alcune istanze di altre classi. Questa class di confronto deve implementare l’interfaccia java.util.Comparator.

  • Capace di confrontare due oggetti dello stesso tipo.
  • Usando questo possiamo implementare many sort sequence e nominare ciascuna, in base alle proprietà delle istanze. EX: Person.id, Person.name, Person.age
  • Possiamo implementare l’interfaccia di confronto con le nostre classi predefinite per l’ordinamento personalizzato.

Esempio:

 public class Employee implements Comparable { private int id; private String name; private int age; private long salary; // Many sort sequences can be created with different names. public static Comparator NameComparator = new Comparator() { @Override public int compare(Employee e1, Employee e2) { return e1.getName().compareTo(e2.getName()); } }; public static Comparator idComparator = new Comparator() { @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 list = new ArrayList(); 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) } } 
  • Per l’ordinamento personalizzato andiamo per comparatore @compare (o1, o2) per altri scenari che andiamo a comparare con @compareTo (o1), senza cambiare codice se vogliamo ordinare più di un campo allora usiamo il comparatore.

Per Java 8 Lambda: Comparator fare riferimento al mio post.

Comparabile dovrebbe essere usato quando si confrontano le istanze della stessa class.

Il comparatore può essere utilizzato per confrontare istanze di classi diverse.

Comparabile è implementato dalla class che ha bisogno di definire un ordinamento naturale per i suoi oggetti. Come gli strumenti di stringa comparabili.

Nel caso in cui si desideri un ordinamento diverso, è ansible implementare il comparatore e definire il proprio modo di confrontare due istanze.

Il comparatore fa tutto ciò che è comparabile, oltre a molto altro.

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

Ho trovato l’approccio migliore per utilizzare i comparatori come classi anonime come segue:

 private static void sortAccountsByPriority(List accounts) { Collections.sort(accounts, new Comparator() { @Override public int compare(AccountRecord a1, AccountRecord a2) { return a1.getRank().compareTo(a2.getRank()); } }); } 

È ansible creare più versioni di tali metodi direttamente all’interno della class che si intende ordinare. Quindi puoi avere:

  • sortAccountsByPriority
  • sortAccountsByType
  • sortAccountsByPriorityAndType

    eccetera…

Ora puoi usare questi metodi di ordinamento ovunque e ottenere il riutilizzo del codice. Questo mi dà tutto ciò che sarebbe paragonabile, oltre a più … quindi non vedo alcun motivo per usare paragonabile.

Direi:

  • se il confronto è intuitivo, quindi con tutti i mezzi implementare Comparabile
  • se non è chiaro se il tuo paragone è intuitivo, usa un Comparatore in quanto è più esplicito e quindi più chiaro per l’anima povera che deve mantenere il codice
  • se c’è più di un confronto intuitivo ansible preferirei un Comparatore, possibilmente costruito da un metodo di fabbrica nella class da confrontare.
  • se il confronto è uno scopo speciale, utilizzare Comparator
  • Se al momento della stesura della class hai solo un caso d’uso di ordinamento usa Paragonabile.
  • Solo quando hai più di una strategia di ordinamento implementa un Comparatore.

I seguenti punti ti aiutano a decidere in quali situazioni si dovrebbe usare Comparabile e in quale Comparatore:

1) Disponibilità del codice

2) Criteri di classificazione singoli contro multipli

3) Arays.sort () e Collection.sort ()

4) Come chiavi in ​​SortedMap e SortedSet

5) Più numero di classi Versus flessibilità

6) Confronti Interclass

7) Ordine naturale

Per un articolo più dettagliato puoi fare riferimento a Quando usare comparatori comparabili e quando usare

C’era stata una domanda simile qui: quando una class dovrebbe essere comparabile e / o comparativa?

Direi quanto segue: Implementabile Comparabile per qualcosa come un ordinamento naturale, ad esempio basato su un ID interno

Implementare un comparatore se si dispone di un algoritmo di confronto più complesso, ad esempio più campi e così via.

Se hai bisogno di ordinamento naturale degli ordini – Utente comparabile SE hai bisogno di ordinamento personalizzato – Usa Comparatore

Esempio:

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

L’ordinamento di ordine naturale sarebbe basato sull’id perché sarebbe univoco e l’ordinamento personalizzato sarebbe il nome e il reparto.

refrences:
Quando una class dovrebbe essere comparabile e / o comparativa? http://javarevisited.blogspot.com/2011/06/comparator-and-comparable-in-java.html

paragonabile:
Ogni volta che vogliamo archiviare solo elementi omogenei e l’ordine di ordinamento naturale predefinito richiesto, possiamo passare alla class implementando un’interfaccia comparable .

comparatore:
Ogni volta che vogliamo memorizzare elementi omogenei ed eterogenei e vogliamo ordinare in ordine di ordinamento personalizzato predefinito, possiamo andare per l’interfaccia comparator .

Se l’ordinamento degli oggetti deve essere basato sull’ordine naturale, utilizzare Paragonabile mentre se è necessario eseguire l’ordinamento sugli attributi di oggetti diversi, utilizzare Comparator in Java.

Principale differenza tra Comparabile e Comparatore:

 +------------------------------------------------------------------------------------+ ¦ 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 classs, Date, Calandar ¦ instances of third-party classs. ¦ +------------------------------------------------------------------------------------+ 

Un approccio molto semplice è supporre che la class di entity framework in questione sia rappresentata nel database e quindi nella tabella di database avresti bisogno di un indice costituito da campi di class quadro? Se la risposta è sì, implementare comparabili e utilizzare i campi indice per l’ordinamento naturale. In tutti gli altri casi usa il comparatore.

Il mio bisogno era basato sulla data.

Quindi, ho usato Comparable e ha funzionato facilmente per me.

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

Una restrizione con Comparable è che non possono essere utilizzate per raccolte diverse da List.

Se possiedi la class, vai con Comparable . Generalmente viene utilizzato Comparator se non si possiede la class, ma è necessario utilizzarla come TreeSet o TreeMap perché Comparator può essere passato come parametro nel conctructor di TreeSet o TreeMap. Puoi vedere come usare Comparator e Comparable in http://preciselyconcise.com/java/collections/g_comparator.php

Mi è stato chiesto di smistare una determinata gamma di numeri in una migliore del tempo di nlogn in una delle interviste. (Non usando il tipo di conteggio)

L’implementazione di un’interfaccia comparabile su un object consente agli algoritmi di ordinamento implicito di utilizzare il metodo di confronto con quelli sovrascritto per ordinare gli elementi di ordinamento e sarebbe il tempo lineare.

  • Comparatore per molti criteri di confronto
  • Paragonabile quando hai un solo criterio.

La mia lib di annotazione per l’implementazione di Comparable and Comparator :

 public class Person implements Comparable { 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); } } 

Clicca sul link per vedere altri esempi. http://code.google.com/p/compamatic/wiki/CompamaticByExamples