2013-04-17 29 views
25

Mam dwa obiekty Java, które są tworzone z tej samej klasy.Jak porównać dwa obiekty Java

MyClass myClass1 = new MyClass(); 
MyClass myClass2 = new MyClass(); 

Jeżeli ustawić zarówno ich właściwości, aby dokładnie te same wartości, a następnie sprawdzić, czy są one takie same

if(myClass1 == myClass2){ 
    // objects match 
    ... 

} 

if(myClass1.equals(myClass2)){ 
    // objects match 
    ... 

} 

Jednak żadna z tych metod zwraca wartość true. Sprawdziłem właściwości każdego i pasują do siebie.

Jak porównać te dwa obiekty, aby sprawdzić, czy są one identyczne?

+0

Zrobiłem Google to, ale wszystkie przykłady, które znalazłem nigdy nie wyjaśniały, że musiałaś zastąpić metodę równości. –

+0

@AndroidAddict: Dlaczego więc nie zadałeś tego pytania? –

Odpowiedz

71

Musisz podać własną implementację equals() w MyClass.

@Override 
public boolean equals(Object other) { 
    if (!(other instanceof MyClass)) { 
     return false; 
    } 

    MyClass that = (MyClass) other; 

    // Custom equality check here. 
    return this.field1.equals(that.field1) 
     && this.field2.equals(that.field2); 
} 

Należy również zastąpić hashCode() jeśli jest jakaś szansa swoich obiektów używane w tabeli mieszania. reasonable implementation byłoby połączyć kody hash pól obiektu jest z czymś takim:

@Override 
public int hashCode() { 
    int hashCode = 1; 

    hashCode = hashCode * 37 + this.field1.hashCode(); 
    hashCode = hashCode * 37 + this.field2.hashCode(); 

    return hashCode; 
} 

Zobacz this question więcej szczegółów na temat implementacji funkcji skrótu.

+1

Dlaczego 37? Prime? – Aubin

+1

@Aubin Zwykle liczby pierwsze są używane w generowaniu kodu skrótu. Jeśli się nie mylę, zmniejsza to ryzyko wystąpienia kolizji na wygenerowanych haszach. Dlaczego używać 37, myślę, że jest to po prostu popularny wybór, nie znam żadnego konkretnego powodu używania 37 zamiast, powiedzmy, 13. – afsantos

+0

Dziękuję - wszystko tak naprawdę. Wszyscy postawili mnie na właściwej drodze, ale mogę tylko zaakceptować jeden jako poprawny. –

5

Trzeba prawidłowo przesłonić metodę equals() z klasy Object

Edit: Myślę, że moja pierwsza reakcja była źle prawdopodobnie dlatego, że nie było zbyt precyzyjne. Postanowiłem więc dodać więcej wyjaśnień.

Dlaczego trzeba zastąpić equals()? Cóż, ponieważ to jest w domenie dewelopera, aby zdecydować, co to znaczy, że dwa obiekty są równe. Równość referencyjna nie wystarcza w większości przypadków.

Na przykład wyobraź sobie, że masz HashMap, którego klucze są typu Person. Każda osoba ma imię i adres. Teraz chcesz znaleźć szczegółową fasolę za pomocą klucza. Problem polega na tym, że zazwyczaj nie można utworzyć instancji z takim samym odniesieniem, jak ten na mapie. To, co robisz, to stworzyć kolejną instancję klasy Osoba. Oczywiście, operator == nie będzie działał tutaj i musisz użyć equals().

Ale teraz dochodzimy do innego problemu. Wyobraźmy sobie, że twoja kolekcja jest bardzo duża i chcesz przeprowadzić wyszukiwanie. Naiwna implementacja porównałaby twój kluczowy obiekt z każdą instancją na mapie za pomocą equals(). To jednak byłoby bardzo ekspansywne. I tu pojawia się hashCode(). Jak zauważyli inni, hashcode to jedna liczba, która nie musi być unikalna. Ważnym wymogiem jest to, że gdy equals() daje true dla dwóch obiektów, hashCode() musi zwrócić tę samą wartość dla obu z nich. Odwrotna implikacja nie zachodzi, co jest dobre, ponieważ hashcode oddziela nasze klucze na rodzaj wiader. Mamy niewielką liczbę instancji klasy Osoba w pojedynczym wiadrze. Kiedy przeprowadzamy wyszukiwanie, algorytm może od razu przejść do poprawnego zasobnika i dopiero teraz wykonać równe dla każdej instancji. Dlatego implementacja dla hashCode() musi rozdzielać obiekty tak równomiernie, jak to tylko możliwe, między segmentami.

Jest jeszcze jeden punkt. Niektóre kolekcje wymagają prawidłowej implementacji metody hashCode() w klasach, które są używane jako klucze nie tylko ze względu na wydajność. Oto przykłady: HashSet i LinkedHashSet. Jeśli nie przesłonią hashCode(), domyślna metoda hashCode() obiektu pozwoli wielu obiektom, które można uznać za "znaczące", aby zostały dodane do zestawu "nie można duplikatów".

Część zbiorów, które korzystają hashCode()

  • Hashset
  • LinkedHashSet
  • HashMap

spojrzeć na tych dwóch klas z Apache Commons, które pozwalają na wdrożenie equals() i hashCode() łatwo

7

Należy zastąpić equals i hashCode.
equals porówna obiektów dla równości w zależności od właściwości trzeba i hashCode jest obowiązkowe w celu obiektami być prawidłowo wykorzystane w Collections i Maps

2

1) == ocenia równości odniesienia w tym przypadku
2) nie jestem zbyt pewny co do równości, ale dlaczego nie po prostu przesłonić metodę porównania i umieścić ją w MyClass?

5

Musisz wdrożyć metodę equals() w swoim MyClass.

Powód, dla którego == nie zadziałał, polega na sprawdzeniu, czy odnoszą się do tej samej instancji. Ponieważ zrobiłeś dla każdego z nich new, każda z nich jest inną instancją.

Przyczyną, dla której equals() nie zadziałało, jest fakt, że nie został on jeszcze wdrożony. Domyślne zachowanie to to samo, co ==.

Należy również wdrożyć hashcode(), jeśli zamierzasz zaimplementować equals(), ponieważ wiele kolekcji java.util tego wymaga.

+0

Niezłe wyjaśnienie. Krótko i na temat. – tommyO

Powiązane problemy