Załóżmy, że utworzyłem jeden obiekt i dodałem go do mojego ArrayList
. Jeśli następnie utworzę inny obiekt z dokładnie tym samym wejściem konstruktora, czy contains()
metoda oceni te dwa obiekty jako takie same? Załóżmy, że konstruktor nie robi nic śmiesznego z danymi wejściowymi, a zmienne przechowywane w obu obiektach są identyczne.
ArrayList<Thing> basket = new ArrayList<Thing>();
Thing thing = new Thing(100);
basket.add(thing);
Thing another = new Thing(100);
basket.contains(another); // true or false?
class Thing {
public int value;
public Thing (int x) {
value = x;
}
equals (Thing x) {
if (x.value == value) return true;
return false;
}
}
Czy w ten sposób class
należy wprowadzić contains()
zwrot, aby uzyskać zwrot true
?
java
object
arraylist
evaluation
Mantas Vidutis
źródło
źródło
Object
raczej niżThing
. Jeśli tego nie zrobisz, metoda równości nie zostanie użyta. :)Collections
robić swoje rzeczy w sposób zoptymalizowany, co oznacza, żecontains()
najpierw sprawdzahashCode
s dwóch obiektów, a dopiero potem wywołujeequals()
. JeślihashCode
s są różne (co zawsze ma miejsce w dwóch różnych przypadkachThing
),equals()
metoda nie zostanie wywołana. Zasadniczo, kiedy przesłoniszequals()
, nie powinieneś również zapomnieć o przesłonięciuhashCode()
.Myślę, że powinny to być właściwe wdrożenia
źródło
if
instrukcja jest niepotrzebna.instanceof
wystarczy.object != null
Warunek nie jest konieczny, ponieważobject instanceof Thing
sprawdza obiekt nie jest zbyt NULL.ArrayList używa metody equals zaimplementowanej w klasie (klasa Thing w twoim przypadku) do wykonania porównania equals.
źródło
Zasadniczo powinieneś również nadpisywać za
hashCode()
każdym razemequals()
, gdy nadpisujesz , nawet jeśli tylko dla zwiększenia wydajności.HashCode()
decyduje, w którym „segmencie” Twój obiekt zostanie posortowany podczas porównywania, więc wszelkie dwa obiekty, któreequal()
zostaną ocenione jako prawda, powinny zwrócić to samohashCode
value()
. Nie pamiętam domyślnego zachowaniahashCode()
(jeśli zwraca 0, wówczas kod powinien działać, ale powoli, ale jeśli zwróci adres, kod nie powiedzie się). Pamiętam kilka razy, kiedy mój kod zawiódł, ponieważ zapomniałem nadpisaćhashCode()
. :)źródło
Używa metody równości na obiektach. Tak więc, chyba że Przesłonięcie Thing jest równe i używa zmiennych przechowywanych w obiektach do porównania, nie zwróci true dla
contains()
metody.źródło
Musisz napisać:
Teraz działa ;)
źródło
Chciałem tylko zauważyć, że następująca implementacja jest niepoprawna, gdy
value
nie jest typem pierwotnym:W takim przypadku proponuję:
źródło
Inne plakaty dotyczyły pytania o sposób działania funkcji zawiera ().
Równie ważnym aspektem twojego pytania jest to, jak poprawnie wdrożyć equals (). Odpowiedź na to pytanie naprawdę zależy od tego, co stanowi równość obiektów dla tej konkretnej klasy. W podanym przykładzie, jeśli masz dwa różne obiekty, które mają x = 5, czy są one równe? To naprawdę zależy od tego, co próbujesz zrobić.
Jeśli interesuje Cię tylko równość obiektów, wówczas domyślna implementacja .equals () (ta dostarczona przez Object) używa tylko tożsamości (tj. This == other). Jeśli tego właśnie chcesz, to po prostu nie implementuj równości () w swojej klasie (niech dziedziczy po Object). Kod, który napisałeś, choć poprawny, jeśli szukasz tożsamości, nigdy nie pojawiłby się w prawdziwej klasie b / c, ale nie zapewnia żadnej korzyści w porównaniu z użyciem domyślnej implementacji Object.equals ().
Jeśli dopiero zaczynasz pracę z tymi rzeczami, zdecydowanie polecam książkę Effective Java autorstwa Joshua Blocha. Jest to świetna lektura i obejmuje tego rodzaju rzeczy (plus jak poprawnie zaimplementować equals (), gdy próbujesz zrobić więcej niż porównania oparte na tożsamości)
źródło
Skrót z JavaDoc :
boolean zawiera (Obiekt o)
Zwraca wartość true, jeśli ta lista zawiera określony element. Bardziej formalnie, zwraca true, jeśli tylko ta lista zawiera co najmniej jeden element e taki, że (o == null? E == null: o.equals (e))
źródło