Kiedy klasa powinna być porównywalna i / lub porównawcza?

138

Widziałem klasy, które implementują zarówno Porównywalną, jak i Porównawczą . Co to znaczy? Dlaczego miałbym używać jednego nad drugim?

Nick Heiner
źródło
18
Czytałeś o nich javadoc? Dość jasno opisuje to, co różni.
skaffman
1
Co jest porównywalne i porównawcze oraz kiedy używać porównywarki i komparatora. Aby je poznać, przeczytaj ten link. pomoże ci to zrozumieć ich zachowanie i użycie. http://iandjava.blogspot.in/2012/10/comparable-and-comparator.html
RockStar
6
To dobre pytanie z dobrą, obiektywną odpowiedzią. Jestem przerażony, że jest zamknięty.
Russell Silva
3
Inne pytania dotyczące StackOverflow nazywają to ostatecznym pytaniem „Jaka jest różnica między komparatorem a porównywalnym”. Dlaczego jest oznaczony jako „nie konstruktywny”? Jako nowicjusz w Javie było to bardzo przydatne pytanie!
Pete

Odpowiedzi:

241

Poniższy tekst pochodzi z książki Komparator vs Porównywalny

Porównywalny

Porównywalny przedmiot jest w stanie porównać się z innym obiektem. Sama klasa musi implementować java.lang.Comparableinterfejs, aby móc porównać jej instancje.

Komparator

Obiekt porównawczy może porównywać dwa różne obiekty. Klasa nie porównuje swoich instancji, ale instancje innych klas. Ta klasa porównawcza musi implementować java.util.Comparatorinterfejs.

Dan
źródło
szczegółowe wyjaśnienie zastosowań zarówno Komparatora, jak i porównywarki: sysdotoutdotprint.com/index.php/2017/03/28/ ...
mel3kings
2
Kolejny dobry artykuł: codecramp.com/java-comparable-vs-comparator
EMM
@ mel3kings - Link nie jest już dostępny.
Gaurav
152

Implementacja Comparableoznacza „ Mogę porównać siebie z innym obiektem. Jest to zwykle przydatne, gdy istnieje jedno naturalne porównanie domyślne.

Implementacja Comparatoroznacza „ Mogę porównać dwa inne obiekty. Jest to zazwyczaj przydatne, gdy istnieje wiele sposobów porównywania dwóch wystąpień typu - np. Można porównać ludzi według wieku, imienia itp.

Jon Skeet
źródło
1
Witaj skeet, czy możesz upuścić kod za pomocą porównywarki i komparatora.
Mdhar9e
5
@ mdhar9e: Istnieje wiele przykładów - jeśli masz trudności z przetłumaczeniem ich na swój konkretny scenariusz, podaj więcej informacji w nowym pytaniu.
Jon Skeet
2
@alireza: W drugim akapicie podałem już przykład: mając różne komparatory, można posortować tę samą kolekcję (osoby) według różnych właściwości (wiek, imię itp.). Nie możesz tego zrobić po prostu wykonując Personnarzędzie Comparable, ponieważ nie możesz wtedy zmienić sposobu porównywania dwóch osób.
Jon Skeet
1
@feelgoodandprogramming: Nie, to są różne algorytmy sortowania . Potencjalnie są tu trzy fragmenty kodu, w trzech różnych klasach: 1) Sam podmiot, np Person. 2) komparator, np. PersonAgeComparatorKtóry jest w stanie porównać dwa różne podmioty i zdecydować, który powinien zająć pierwsze miejsce w określonej kolejności sortowania. 3) Kod sortowania, który pobiera zbiór jednostek i komparatora, a następnie sortuje ten zbiór przy użyciu komparatora w celu określenia kolejności.
Jon Skeet,
2
@RishiKeshPathak: Cóż, bardziej chodzi o to, że używasz Comparable, jeśli jest tylko jedna oczywista rzecz do porównania. I nawet wtedy można po prostu napisać komparatora. Jeśli masz dwa różne programy korzystające z tej samej klasy, a jeden chce sortować tylko według wieku, a drugi według nazwy, przynajmniej jeden z nich będzie musiał użyć komparatora.
Jon Skeet
38

Porównywalny pozwala klasie na implementację własnego porównania:

  • jest w tej samej klasie (często jest to zaleta)
  • może być tylko jedna implementacja (więc nie możesz jej użyć, jeśli chcesz mieć dwa różne przypadki)

Dla porównania, komparator jest porównaniem zewnętrznym:

  • zazwyczaj występuje w wyjątkowym przypadku (w tej samej klasie lub w innym miejscu)
  • Państwo wymienić każdą realizację z okazji chcesz uporządkować rzeczy
  • możesz podać komparatory dla klas, których nie kontrolujesz
  • implementacja jest użyteczna, nawet jeśli pierwszy obiekt ma wartość null

W obu wdrożeniach nadal możesz wybrać, z czym chcesz się porównywać . Dzięki rodzajom możesz to zadeklarować i sprawdzić w czasie kompilacji. Zwiększa to bezpieczeństwo, ale wyzwaniem jest też określenie odpowiedniej wartości.

Jako wskazówkę, generalnie używam najbardziej ogólnej klasy lub interfejsu, z którym można porównać ten obiekt, we wszystkich przypadkach użycia, jakie wyobrażam ... Jednak definicja niezbyt precyzyjna! :-(

  • Comparable<Object>pozwala na użycie go we wszystkich kodach w czasie kompilacji (co jest dobre w razie potrzeby lub złe, jeśli nie, i tracisz błąd w czasie kompilacji); Twoja implementacja musi radzić sobie z obiektami i rzutować w razie potrzeby, ale w niezawodny sposób.
  • Comparable<Itself> jest bardzo surowa, wręcz przeciwnie.

Zabawne, kiedy podklasujesz siebie do podklasy, podklasa musi być również porównywalna i solidna (w przeciwnym razie złamałaby zasadę Liskova i spowodowała błędy w czasie wykonywania).

KLE
źródło
20

java.lang.Comparable

  1. Aby zaimplementować Comparableinterfejs, klasa musi implementować jedną metodęcompareTo()

    int a.compareTo(b)

  2. Musisz zmodyfikować klasę, której instancję chcesz sortować. Aby można było utworzyć tylko jedną sekwencję sortowania na klasę.

java.util.Comparator

  1. Aby zaimplementować interfejs komparatora, klasa musi implementować jedną metodę compare()

    int compare (a,b)

  2. Tworzysz klasę oddzielnie od klasy, której instancję chcesz posortować. Aby można było utworzyć wiele kolejności sortowania dla każdej klasy.
codiacTushki
źródło
14

Comparable służy do zapewniania domyślnej kolejności obiektów danych, na przykład jeśli obiekty danych mają naturalny porządek.

A Comparatorreprezentuje samo zamówienie do określonego użytku.

starblue
źródło
8

Comparablejest zwykle preferowany. Ale czasami klasa już implementuje Comparable, ale chcesz posortować według innej właściwości. Wtedy jesteś zmuszony użyć Comparator.

Niektóre klasy zapewniają w rzeczywistości Comparatorstypowe przypadki; na przykład Strings domyślnie rozróżniana jest wielkość liter podczas sortowania, ale istnieje również statyczny Comparatorcall CASE_INSENSITIVE_ORDER.

Michael Myers
źródło
7
Nie jestem pewien, czy zgadzam się z preferowaniem porównywalnego. Niektóre obiekty mają silne poczucie porządku naturalnego - mianowicie liczby we wszystkich ich formach: liczby naturalne, liczby rzeczywiste, daty itp. Jednak nawet innym stosunkowo prymitywnym obiektom, takim jak ciągi znaków, brakuje uniwersalnego porządku. W przypadku bardziej złożonych obiektów, takich jak jednostka z modelu domeny aplikacji, implementacja Comparable jest zwykle błędem. Ich liczne właściwości sprawiają, że zbyt trudno jest przewidzieć, jaki porządek będzie poszukiwany najczęściej.
erickson
6

oto kilka różnic między komparatorem a porównywalnym, które znalazłem w sieci:

  1. Jeśli widzisz logiczną różnicę między tymi dwoma, komparator w Javie porównuje dwa dostarczone mu obiekty, podczas gdy interfejs Comparable porównuje „to” odwołanie z określonym obiektem.

  2. Porównywalny w Javie służy do implementacji naturalnego uporządkowania obiektów. W klasach Java API String, Date i wrapper implementują porównywalny interfejs.

  3. Jeśli jakaś klasa implementuje porównywalny interfejs w Javie, wówczas zbiór tego obiektu List lub Array może być sortowany automatycznie przy użyciu metody Collections.sort () lub Array.sort (), a obiekt zostanie posortowany na podstawie naturalnej kolejności zdefiniowanej przez metodę CompareTo.

  4. Obiekty, które implementują Comparable w Javie, mogą być używane jako klucze w posortowanej mapie lub elementy w posortowanym zbiorze, na przykład TreeSet, bez określania jakiegokolwiek komparatora.

strona: Jak korzystać z komparatora i porównywalnego w Javie? Z przykładem

Czytaj więcej: Jak korzystać z komparatora i porównywalnego w Javie? Z przykładem

javapassion
źródło
5

Comparablejest dla obiektów z naturalnym uporządkowaniem. Sam obiekt wie, jak ma być zamówiony.
Comparatordotyczy przedmiotów bez naturalnego uporządkowania lub gdy chcesz użyć innego uporządkowania.

Michael Lloyd Lee mlk
źródło
4

Różnica między interfejsami komparatora i porównywalnych

Comparable służy do porównywania się z innym obiektem.

Comparator służy do porównania dwóch typów danych - obiektów.

SravaniChowdary.Gorijavolu
źródło
2

Jeśli widzisz, logiczną różnicą między tymi dwoma jest Comparatorw Javie porównanie dwóch dostarczonych mu obiektów, podczas gdy Comparableinterfejs porównuje „to” odniesienie z określonym obiektem.

Comparablew Javie służy do implementacji naturalnego uporządkowania obiektów. W klasach Java API String, Date i wrapper implementują Comparableinterfejs.

Jeśli jakakolwiek klasa zaimplementować Comparableinterfejs w języku Java, a następnie kolekcję tego obiektu albo Listczy Arraymogą być sortowane automatycznie za pomocą Collections.sort()lub Array.sort()metodę i obiekt zostanie tam sortowane na podstawie kolejności określonej przez naturalne compareTometody.

Obiekty, które są implementowane Comparablew Javie, mogą być używane jako klucze w posortowanej mapie lub na przykład elementy w posortowanym zestawie TreeSet, bez określania żadnego Comparator.

Srinivas
źródło
0

Moja biblioteka adnotacji do implementacji porównywalnego i komparatora:

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

Kliknij łącze, aby zobaczyć więcej przykładów. compamatic

Jianmin Liu
źródło
3
Witamy w stackoverflow. To pytanie jest stare i zostało już udzielone. Zazwyczaj najlepiej nie wskrzeszać przestarzałych wątków, chyba że Twoja odpowiedź wniesie coś znacząco nowego lub innego niż poprzednie odpowiedzi.
oferuje