Qual'è la differenza tra compare () e compareTo ()?


Risposte:


160

Da JavaNotes :

  • a.compareTo(b):
    Interfaccia comparabile: confronta i valori e restituisce un int che indica se i valori sono inferiori, uguali o maggiori di.
    Se gli oggetti della tua classe hanno un ordine naturale , implementa l' Comparable<T>interfaccia e definisci questo metodo. Tutte le classi Java che hanno un ordinamento naturale implementare Comparable<T>- ad esempio: String, classi wrapper ,BigInteger

  • compare(a, b):
    Interfaccia di confronto : confronta i valori di due oggetti. Questo è implementato come parte Comparator<T>dell'interfaccia e l' uso tipico è quello di definire una o più piccole classi di utilità che lo implementano, per passare a metodi come sort()o per l'uso ordinando strutture di dati come TreeMapeTreeSet . Potresti voler creare un oggetto Comparator per quanto segue:

    • Confronti multipli . Fornire diversi modi per ordinare qualcosa. Ad esempio, potresti voler ordinare una classe Person per nome, ID, età, altezza, ... Definiresti un Comparatore per ciascuno di questi da passare al sort()metodo.
    • Classe di sistema Per fornire metodi di confronto per classi su cui non si ha alcun controllo. Ad esempio, potresti definire un comparatore per stringhe che le confronti in base alla lunghezza.
    • Pattern di strategia Per implementare un pattern di strategia, che è una situazione in cui si desidera rappresentare un algoritmo come un oggetto che è possibile passare come parametro, salvare in una struttura di dati, ecc.

Se gli oggetti della tua classe hanno un ordinamento naturale, potresti non aver bisogno di compare ().


Riepilogo da http://www.digizol.com/2008/07/java-sorting-comparator-vs-comparable.html

Comparabile
Un oggetto comparabile è in grado di confrontarsi con un altro oggetto.

Comparatore
Un oggetto comparatore è in grado di confrontare due oggetti diversi. La classe non confronta le sue istanze, ma le istanze di un'altra classe.


Contesti dei casi d'uso:

Interfaccia comparabile

Il metodo uguale e ==e!= operatori verificano l'uguaglianza / disuguaglianza, ma non forniscono un modo per verificare i valori relativi .
Alcune classi (ad esempio, String e altre classi con un ordinamento naturale) implementano l' Comparable<T>interfaccia, che definisce un compareTo()metodo.
Dovrai implementarlo Comparable<T>nella tua classe se vuoi usarlo con i metodi Collections.sort()o Arrays.sort().

Definizione di un oggetto Comparator

Puoi creare comparatori per ordinare qualsiasi modo arbitrario per qualsiasi classe .
Ad esempio, la Stringclasse definisce il CASE_INSENSITIVE_ORDERcomparatore .


La differenza tra i due approcci può essere collegata alla nozione di:
Raccolta ordinata :

Quando una raccolta viene ordinata, significa che è possibile iterare nella raccolta in un ordine specifico (non casuale) (a Hashtablenon è ordinato).

Una collezione con un ordine naturale non è solo ordinata, ma ordinata . Definire un ordine naturale può essere difficile! (come nell'ordine delle corde naturale ).


Un'altra differenza, sottolineata da HaveAGuess nei commenti :

  • Comparable è nell'implementazione e non è visibile dall'interfaccia, quindi quando esegui l'ordinamento non sai davvero cosa succederà.
  • Comparator ti rassicura che l'ordine sarà ben definito.

2
Poiché questa risposta è esaustiva, ecco qualcosa che mi infastidisce di Comparable che potresti aggiungere: è nell'implementazione e non è visibile dall'interfaccia, quindi quando esegui l'ordinamento non sai davvero cosa accadrà. L'uso di un comparatore ti rassicura sul fatto che l'ordine sarà ben definito
AvereAGuess

@HaveAGuess buon punto. Ho incluso il tuo commento nella risposta per una maggiore visibilità.
VonC

gli oggetti hanno un ordine naturale, cosa significa ordine naturale qui? Un membro di dati stringa per es. Il nome nella classe dipendente ha un ordine naturale?
Narendra Jaggi

@NarendraJaggi Vedi en.wikipedia.org/wiki/Enumeration . Un ordine che facilita l'enumerazione. "Naturale" nel senso che un determinato ordine nel set di indici fornisce un modo univoco per elencare l'elemento successivo con un'enumerazione parziale
VonC

2
@VedantKekan Grazie. Ho ripristinato 2 collegamenti in questa risposta.
VonC

16

compareTo()è Comparabledall'interfaccia.

compare()è Comparatordall'interfaccia.

Entrambi i metodi fanno la stessa cosa, ma ogni interfaccia viene utilizzata in un contesto leggermente diverso.

L' interfaccia Comparable viene utilizzata per imporre un ordinamento naturale agli oggetti della classe di implementazione. Il compareTo()metodo è chiamato metodo di confronto naturale. L' interfaccia Comparator viene utilizzata per imporre un ordinamento totale sugli oggetti della classe di implementazione. Per ulteriori informazioni, vedere i collegamenti per sapere esattamente quando utilizzare ciascuna interfaccia.


puoi fare degli esempi? Entrambi i metodi danno le stesse risposte?

Non so perché "Comparable" è per l'ordinamento naturale? Possiamo personalizzarlo, no?
c-an

14

Somiglianze:
entrambi sono modi personalizzati per confrontare due oggetti.
Entrambi restituiscono una intdescrizione della relazione tra due oggetti.

Differenze: il metodo compare()è un metodo che sei obbligato a implementare se implementi l' Comparatorinterfaccia. Ti consente di passare due oggetti nel metodo e restituisce una intdescrizione della loro relazione.

Comparator comp = new MyComparator();
int result = comp.compare(object1, object2);

Il metodo compareTo()è un metodo che sei obbligato a implementare se implementi l' Comparableinterfaccia. Consente di confrontare un oggetto con oggetti di tipo simile.

String s = "hi";
int result = s.compareTo("bye");

Riepilogo:
fondamentalmente sono due modi diversi per confrontare le cose.


9

I metodi non devono dare le stesse risposte. Dipende da quali oggetti / classi li chiami.

Se stai implementando le tue classi che sai di voler confrontare a un certo punto, potresti fare in modo che implementino l'interfaccia Comparable e implementino il metodo compareTo () di conseguenza.

Se stai utilizzando alcune classi di un'API che non implementano l'interfaccia Comparable, ma desideri comunque confrontarle. Cioè per l'ordinamento. Puoi creare la tua classe che implementa l'interfaccia di Comparator e nel suo metodo compare () implementare la logica.


3

L' interfaccia comparabile contiene un metodo chiamato compareTo(obj)che accetta solo un argomento e si confronta con un'altra istanza o oggetti della stessa classe.

L' interfaccia del comparatore contiene un metodo chiamato compare(obj1,obj2)che accetta due argomenti e confronta il valore di due oggetti della stessa classe o di classi diverse.


3
compareTo(T object)

proviene dall'interfaccia java.lang.Comparable, implementata per confrontare questo oggetto con un altro per fornire un valore int negativo per questo oggetto inferiore a, 0 per uguale o positivo per maggiore dell'altro. Questo è il metodo di confronto più conveniente, ma deve essere implementato in ogni classe che si desidera confrontare.

compare(T obj1, T obj2)

proviene dall'interfaccia java.util.Comparator, implementata in una classe separata che confronta gli oggetti di un'altra classe per fornire un valore int negativo per il primo oggetto minore di, 0 per uguale o un valore positivo per maggiore del secondo oggetto. È necessario quando non è possibile fare in modo che una classe implementi compareTo () perché non è modificabile. Viene anche utilizzato quando si desiderano modi diversi per confrontare gli oggetti, non solo uno (ad esempio per nome o età).


3

Usando Comparator, possiamo avere n numero di logica di confronto scritta per una classe .

Per esempio

Per una classe di auto

Possiamo avere una classe di confronto da confrontare in base al numero di modello dell'auto. Possiamo anche avere una classe di confronto da confrontare in base all'anno del modello dell'auto.

Classe di auto

public class Car  {

    int modelNo;

    int modelYear;

    public int getModelNo() {
        return modelNo;
    }

    public void setModelNo(int modelNo) {
        this.modelNo = modelNo;
    }

    public int getModelYear() {
        return modelYear;
    }

    public void setModelYear(int modelYear) {
        this.modelYear = modelYear;
    }

}

Comparatore n. 1 basato sul modello n

public class CarModelNoCompartor implements Comparator<Car>{

    public int compare(Car o1, Car o2) {

        return o1.getModelNo() - o2.getModelNo();
    }

}

Comparatore n. 2 basato sull'anno del modello

public class CarModelYearComparator implements Comparator<Car> {

    public int compare(Car o1, Car o2) {

        return o1.getModelYear() - o2.getModelYear();
    }

}

Ma questo non è possibile con il caso di Comparable .

In caso di interfaccia Comparable, possiamo avere una sola logica nel metodo compareTo () .


2

Il rapporto dell'oggetto che ha questo metodo e dei suoi collaboratori è diverso.

compareTo()è un metodo dell'interfaccia Comparable , quindi viene utilizzato per confrontare QUESTA istanza con un'altra.

compare()è un metodo dell'interfaccia Comparator , quindi viene utilizzato per confrontare tra loro due diverse istanze di un'altra classe.

Se vuoi, l'implementazione Comparablesignifica che le istanze della classe possono essere facilmente confrontate.
L'implementazione Comparatorsignifica che le istanze sono adatte per confrontare oggetti diversi (di altre classi).


2

La differenza principale è nell'uso delle interfacce:

Comparable (che ha compareTo ()) richiede che gli oggetti vengano confrontati (per utilizzare una TreeMap o per ordinare un elenco) per implementare quell'interfaccia. Ma cosa succede se la classe non implementa Comparable e non è possibile modificarla perché fa parte di una libreria di terze parti? Quindi devi implementare un comparatore, che è un po 'meno comodo da usare.


2

compareTo()viene chiamato su un oggetto, per confrontarlo con un altro oggetto. compare()viene chiamato su un oggetto per confrontare altri due oggetti.

La differenza è dove viene definita la logica che esegue il confronto effettivo.


Non è quella che definirei una risposta fantastica, ma non credo che meriti un voto negativo.
Paul Tomblin,

D'accordo, personalmente mi riservo i voti negativi per risposte sbagliate o fuorvianti. Questo è decisamente corretto.
Joachim Sauer

Allora dove sono quelle persone "amichevoli" che mi hanno svalutato? Questa è la mia seconda risposta corretta che è stata sottovalutata perché qualcuno ha mancato il punto. O il punto di downvoting o il punto della mia risposta. La vita è così crudele .. ;-)
Abgan

0

Quando si desidera ordinare un List che include l'Object Foo, la classe Foo deve implementare l'interfaccia Comparable, perché il metodo di ordinamento della List utilizza questo metodo.

Quando si desidera scrivere una classe Util che confronta altre due classi, è possibile implementare la classe Comparator.


0


Nome tabella dipendenti , DoB, Salary
Tomas, 2/10/1982, 300
Daniel, 3/11/1990, 400
Kwame, 2/10/1998, 520

L' interfaccia Comparable ti consente di ordinare un elenco di oggetti ad es. Dipendenti con riferimento a un campo principale - ad esempio, puoi ordinare per nome o per stipendio con il metodo CompareTo ()

emp1.getName().compareTo(emp2.getName())

Un'interfaccia più flessibile per tali requisiti è fornita dall'interfaccia Comparator , il cui unico metodo è compare ()

public interface Comparator<Employee> {
 int compare(Employee obj1, Employee obj2);
}

Codice di esempio

public class NameComparator implements Comparator<Employee> {

public int compare(Employee e1, Employee e2) {
     // some conditions here
        return e1.getName().compareTo(e2.getName()); // returns 1 since (T)omas > (D)an 
    return e1.getSalary().compareTo(e2.getSalary()); // returns -1 since 400 > 300
}

}


0

Un altro punto:

  • compareTo()proviene Comparabledall'interfaccia e compare()proviene Comparatordall'interfaccia.
  • Comparableviene utilizzato per definire un ordinamento predefinito per gli oggetti all'interno di una classe mentre Comparatorviene utilizzato per definire un ordinamento personalizzato da passare a un metodo.

0

C'è anche un aspetto tecnico che dovrebbe essere sottolineato. Supponi di aver bisogno della parametrizzazione del comportamento di confronto da una classe client e ti stai chiedendo se utilizzare Comparableo Comparatorper un metodo come questo:

class Pokemon {
    int healthPoints;
    int attackDamage;
    public void battle (Comparable<Pokemon> comparable, Pokemon opponent) {
        if (comparable.compareTo(opponent) > 0) { //comparable needs to, but cannot, access this.healthPoints for example
            System.out.println("battle won");
        } else {
            System.out.println("battle lost");
        }
    }
}

comparablesarebbe un lambda o un oggetto, e non c'è modo comparabledi accedere ai campi di thisPokemon. (In un lambda, si thisriferisce all'istanza della classe esterna nell'ambito del lambda, come definito nel testo del programma.) Quindi questo non funziona e dobbiamo usare a Comparatorcon due argomenti.


0

Usa l'interfaccia Comparable per l'ordinamento sulla base di più di un valore come età, nome, nome_dipartimento ... Per un valore usa l'interfaccia Comparator


-2
Important Answar
String name;
int roll;

public int compare(Object obj1,Object obj2) { // For Comparator interface
    return obj1.compareTo(obj1);
}

public int compareTo(Object obj1) { // For Comparable Interface
    return obj1.compareTo(obj);
}

Qui in return obj1.compareTo(obj1)o return obj1.compareTo(obj)dichiarazione prendi solo Object; primitiva non è consentita. Per esempio

name.compareTo(obj1.getName()) // Correct Statement.

Ma

roll.compareTo(obj1.getRoll()) 
// Wrong Statement Compile Time Error Because roll 
// is not an Object Type, it is primitive type.

name è String Object quindi ha funzionato. Se vuoi ordinare il numero del rotolo di studenti, usa il codice sottostante.

public int compareTo(Object obj1) { // For Comparable Interface
    Student s = (Student) obj1;
    return rollno - s.getRollno();
}  

o

public int compare(Object obj1,Object obj2) { // For Comparator interface
    Student s1 = (Student) obj1;
    Student s2 = (Student) obj2;
    return s1.getRollno() - s2.getRollno();
}  
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.