Jaka jest różnica między compare () i compareTo ()?


Odpowiedzi:


160

Z JavaNotes :

  • a.compareTo(b):
    Porównywalny interfejs: porównuje wartości i zwraca wartość typu int, która mówi, czy wartości są porównywane mniejsze niż, równe lub większe niż.
    Jeśli obiekty Twojej klasy mają naturalną kolejność , zaimplementuj Comparable<T>interfejs i zdefiniuj tę metodę. Wszystkie klasy Java, które mają naturalną kolejność wdrażają Comparable<T>- przykład: String, wrapper klas ,BigInteger

  • compare(a, b):
    Interfejs komparatora: porównuje wartości dwóch obiektów. Jest to implementowane jako część Comparator<T>interfejsu, a typowym zastosowaniem jest zdefiniowanie jednej lub więcej małych klas narzędziowych, które to implementują, w celu przekazania do metod takich jak sort()lub do użycia przez sortowanie struktur danych, takich jak TreeMapiTreeSet . Możesz chcieć utworzyć obiekt komparatora dla następujących:

    • Wiele porównań . Zapewnienie kilku różnych sposobów sortowania czegoś. Na przykład możesz chcieć posortować klasę Person według nazwy, identyfikatora, wieku, wzrostu itp. Dla każdej z nich można zdefiniować komparator, który zostanie przekazany do sort()metody.
    • Klasa systemowa Zapewnia metody porównawcze dla klas, nad którymi nie masz kontroli. Na przykład można zdefiniować komparator dla ciągów znaków, który porówna je według długości.
    • Wzorzec strategii Aby zaimplementować wzorzec strategii, czyli sytuację, w której chcesz przedstawić algorytm jako obiekt, który można przekazać jako parametr, zapisać w strukturze danych itp.

Jeśli obiekty Twojej klasy mają jedną naturalną kolejność sortowania, możesz nie potrzebować funkcji compare ().


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

Porównywalny Porównywalny
przedmiot jest zdolny do porównywania się z innym przedmiotem.

Komparator
Obiekt porównawczy jest w stanie porównać dwa różne obiekty. Klasa nie porównuje swoich instancji, ale instancje innych klas.


Konteksty przypadków użycia:

Porównywalny interfejs

Metoda equals ==i != operatory oraz i operatory testują pod kątem równości / nierówności, ale nie zapewniają sposobu testowania wartości względnych .
Niektóre klasy (np. String i inne klasy z naturalną kolejnością) implementują Comparable<T>interfejs, który definiuje compareTo()metodę.
Będziesz chciał zaimplementować Comparable<T>w swojej klasie, jeśli chcesz go używać z metodami Collections.sort()lub Arrays.sort().

Definiowanie obiektu komparatora

Możesz tworzyć komparatory do sortować w dowolny sposób dla dowolnej klasy .
Na przykład Stringklasa definiuje CASE_INSENSITIVE_ORDERkomparator .


Różnicę między tymi dwoma podejściami można powiązać z pojęciem:
Uporządkowana kolekcja :

Po uporządkowaniu kolekcji oznacza to, że możesz iterować w kolekcji w określonej (nielosowej) kolejności (a Hashtablenie jest uporządkowana).

Kolekcja o naturalnym porządku jest nie tylko uporządkowana, ale posortowana . Zdefiniowanie naturalnego porządku może być trudne!(jak w naturalnym porządku String ).


Kolejna różnica, wskazana przez HaveAGuess w komentarzach :

  • Comparable jest w trakcie implementacji i nie jest widoczny w interfejsie, więc podczas sortowania nie wiesz, co się stanie.
  • Comparator daje pewność, że kolejność będzie dobrze zdefiniowana.

2
Ponieważ ta odpowiedź jest wyczerpująca, oto coś, co mnie denerwuje w Porównywalne, które możesz dodać: Jest w implementacji i nie jest widoczne z interfejsu, więc kiedy sortujesz, naprawdę nie wiesz, co się stanie. Korzystanie z komparatora daje pewność, że kolejność będzie dobrze zdefiniowana
HaveAGuess

@ Miej dobry punkt widzenia. W odpowiedzi zawarłem Twój komentarz, aby uzyskać lepszą widoczność.
VonC

przedmioty mają naturalny porządek, co oznacza tutaj porządek naturalny? Czy element danych typu string, np. Nazwisko w klasie pracownika, ma naturalny porządek?
Narendra Jaggi

@NarendraJaggi Zobacz en.wikipedia.org/wiki/Enumeration . Kolejność ułatwiająca wyliczanie. „Naturalny” w tym sensie, że dana dobra kolejność w zestawie indeksów zapewnia unikalny sposób wyświetlania następnego elementu przy częściowym wyliczeniu
VonC

2
@VedantKekan Dziękuję. Przywróciłem 2 linki w tej odpowiedzi.
VonC

16

compareTo()pochodzi z Comparableinterfejsu.

compare()pochodzi z Comparatorinterfejsu.

Obie metody robią to samo, ale każdy interfejs jest używany w nieco innym kontekście.

Porównywalne interfejs służy do nakładania naturalną kolejność na obiektach klasy wykonawczego. compareTo()Metoda nazywana jest naturalną metodą porównania. Komparator interfejs służy do nałożenia całkowitego uporządkowania na obiektach klasy wykonawczego. Aby uzyskać więcej informacji, zapoznaj się z linkami, aby dokładnie określić, kiedy używać każdego interfejsu.


czy możesz podać przykłady? Obie metody dają takie same odpowiedzi?

Nie wiem, dlaczego „Porównywalny” służy do naturalnego uporządkowania? Możemy to dostosować, prawda?
c-an

14

Podobieństwa:
oba są niestandardowymi sposobami porównywania dwóch obiektów.
Oba zwracają intopis związku między dwoma obiektami.

Różnice: Metoda compare()jest metodą, którą jesteś zobowiązany wdrożyć, jeśli implementujesz Comparatorinterfejs. Pozwala na przekazanie dwóch obiektów do metody i zwraca intopis ich związku.

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

Metoda compareTo()to metoda, którą jesteś zobowiązany wdrożyć, jeśli implementujesz Comparableinterfejs. Pozwala porównać obiekt z obiektami podobnego typu.

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

Podsumowanie:
Zasadniczo są to dwa różne sposoby porównywania rzeczy.


9

Metody nie muszą dawać takich samych odpowiedzi. To zależy od tego, jakie obiekty / klasy je nazywasz.

Jeśli implementujesz własne klasy, o których wiesz, że chcesz je porównać na pewnym etapie, możesz mieć zaimplementować interfejs Comparable i odpowiednio zaimplementować metodę compareTo ().

Jeśli używasz niektórych klas z interfejsu API, które nie implementują interfejsu Comparable, ale nadal chcesz je porównać. Tj. Do sortowania. Możesz utworzyć własną klasę, która implementuje interfejs komparatora, aw jej metodzie compare () zaimplementujesz logikę.


3

Porównywalny interfejs zawiera wywołaną metodę, compareTo(obj)która przyjmuje tylko jeden argument i porównuje się z inną instancją lub obiektami tej samej klasy.

Interfejs komparatora zawiera wywoływaną metodę, compare(obj1,obj2)która pobiera dwa argumenty i porównuje wartości dwóch obiektów z tej samej lub różnych klas.


3
compareTo(T object)

pochodzi z interfejsu java.lang.Comparable, zaimplementowanego w celu porównania tego obiektu z innym w celu uzyskania ujemnej wartości int dla tego obiektu, która jest mniejsza niż, 0 dla równości lub dodatnia dla większego niż inny. Jest to wygodniejsza metoda porównywania, ale musi być zaimplementowana w każdej klasie, którą chcesz porównać.

compare(T obj1, T obj2)

pochodzi z interfejsu java.util.Comparator, zaimplementowanego w oddzielnej klasie, która porównuje obiekty innej klasy w celu uzyskania ujemnej wartości int dla pierwszego obiektu, która jest mniejsza niż, 0 dla równości lub dodatnia dla wartości większej niż drugi obiekt. Jest potrzebny, gdy nie można utworzyć klasy implementującej compareTo (), ponieważ nie można jej modyfikować. Jest również używany, gdy chcesz porównać obiekty na różne sposoby, a nie tylko jeden (na przykład według imienia lub wieku).


3

Używając Komparatora, możemy mieć n liczby logiki porównania napisanej dla klasy .

Na przykład

Dla klasy samochodu

Możemy mieć klasę komparatora do porównania na podstawie numeru modelu samochodu. Możemy również mieć klasę komparatora do porównania na podstawie roku modelowego samochodu.

Klasa samochodu

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

}

Komparator nr 1 oparty na modelu nr

public class CarModelNoCompartor implements Comparator<Car>{

    public int compare(Car o1, Car o2) {

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

}

Komparator nr 2 na podstawie roku modelowego

public class CarModelYearComparator implements Comparator<Car> {

    public int compare(Car o1, Car o2) {

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

}

Ale nie jest to możliwe w przypadku porównywalnego interfejsu.

W przypadku interfejsu Comparable możemy mieć tylko jedną logikę w metodzie compareTo () .


2

Relacja obiektu posiadającego tę metodę i jej współpracowników jest inna.

compareTo()jest metodą interfejsu Comparable , więc jest używana do porównania TEGO wystąpienia z innym.

compare()jest metodą interfejsu Komparator , więc służy do porównywania ze sobą dwóch różnych instancji innej klasy.

Jeśli chcesz, implementacja Comparableoznacza, że ​​instancje klasy można łatwo porównać.
Implementacja Comparatoroznacza, że ​​instancje są przystosowane do porównywania różnych obiektów (innych klas).


2

Główna różnica polega na zastosowaniu interfejsów:

Compareable (który ma funkcję compareTo ()) wymaga porównania obiektów (w celu użycia TreeMap lub sortowania listy) w celu zaimplementowania tego interfejsu. Ale co, jeśli klasa nie implementuje klasy Comparable i nie możesz jej zmienić, ponieważ jest częścią biblioteki innej firmy? Następnie musisz zaimplementować Komparator, który jest nieco mniej wygodny w użyciu.


2

compareTo() jest wywoływana na jednym obiekcie, aby porównać go z innym obiektem. compare()jest wywoływana na jakimś obiekcie w celu porównania dwóch innych obiektów.

Różnica polega na tym, że zdefiniowano logikę, która dokonuje rzeczywistego porównania.


Nie to, co nazwałbym fantastyczną odpowiedzią, ale nie sądzę, że zasługuje na złą opinię.
Paul Tomblin

Zgoda, osobiście rezerwuję głosy przeciw za błędne lub mylące odpowiedzi. Ten jest zdecydowanie poprawny.
Joachim Sauer

Więc gdzie są ci „przyjaźni” ludzie, którzy mnie zlekceważyli? To moja druga poprawna odpowiedź, która została odrzucona, ponieważ ktoś przeoczył sedno sprawy. Albo punkt przegłosowania, albo punkt mojej odpowiedzi. Życie jest takie okrutne .. ;-)
Abgan,

0

Jeśli chcesz posortować Listę, która zawiera Object Foo, klasa Foo musi zaimplementować interfejs Comparable, ponieważ metoda sortowania listy korzysta z tej metody.

Jeśli chcesz napisać klasę Util, która porównuje dwie inne klasy, możesz zaimplementować klasę Comparator.


0


Nazwa tabeli pracowników , data urodzenia, wynagrodzenie
Tomas, 2/10/1982, 300
Daniel, 3/11/1990, 400
Kwame, 2/10/1998, 520

Porównywalne interfejs umożliwia sortowanie listy obiektów np pracownikom odniesieniu do jednej podstawowej dziedzinie - na przykład, można sortować według nazwy lub wynagrodzenia z compareTo () metody

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

Bardziej elastyczny interfejs dla takich wymagań zapewnia interfejs komparatora , którego jedyną metodą jest compare ()

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

Przykładowy kod

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

Jeszcze jeden punkt:

  • compareTo()pochodzi z Comparableinterfejsu i compare()pochodzi z Comparatorinterfejsu.
  • Comparablesłuży do definiowania domyślnej kolejności obiektów w klasie, natomiast Comparatorsłuży do definiowania niestandardowej kolejności przekazywania do metody.

0

Jest jeszcze aspekt techniczny, który należy podkreślić. Powiedzmy, że potrzebujesz parametryzacji zachowania porównania z klasy klienta i zastanawiasz się, czy użyć Comparablelub Comparatordla metody takiej jak ta:

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

comparablebędzie lambda lub obiekt i nie ma sposobu, comparableaby uzyskać dostęp do pól thisPokemona. (W lambdzie thisodnosi się do zewnętrznej instancji klasy w zakresie lambda, zgodnie z definicją w tekście programu). Więc to nie leci i musimy użyć a Comparatorz dwoma argumentami.


0

Użyj porównywalnego interfejsu do sortowania na podstawie więcej niż jednej wartości, takiej jak wiek, imię i nazwisko, dział_nazwa ... Dla jednej wartości użyj interfejsu komparatora


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

Tutaj w oświadczeniu return obj1.compareTo(obj1)lub return obj1.compareTo(obj)weź tylko Object; prymityw jest niedozwolony. Na przykład

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

Ale

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

nazwa to String Object, więc zadziałało. Jeśli chcesz posortować liczbę uczniów, użyj poniższego kodu.

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

lub

public int compare(Object obj1,Object obj2) { // For Comparator interface
    Student s1 = (Student) obj1;
    Student s2 = (Student) obj2;
    return s1.getRollno() - s2.getRollno();
}  
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.