Jak metoda contains() ArrayList ocenia obiekty?

Powiedzmy, że tworzę jeden obiekt i dodaję go do mojego ArrayList. Jeśli następnie wytworzę kolejny obiekt z dokładnie tym samym konstruktorem, czy metoda contains() oceni oba 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 tak powinno być zaimplementowane class, aby mieć contains() return true?

Author: Bakuriu, 2010-04-15

9 answers

ArrayList implements interfejs listy.

Jeśli spojrzysz na Javadoc dla List w metodzie contains zobaczysz, że używa ona metody equals() do oceny, czy dwa obiekty są takie same.

 347
Author: Binary Nerd,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-26 15:38:24

Myślę, że właściwe implementacje powinny być

public class Thing
{
    public int value;  

    public Thing (int x)
    {
        this.value = x;
    }

    @Override
    public boolean equals(Object object)
    {
        boolean sameSame = false;

        if (object != null && object instanceof Thing)
        {
            sameSame = this.value == ((Thing) object).value;
        }

        return sameSame;
    }
}
 53
Author: ChristopheCVB,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-31 19:27:11

ArrayList używa metody equals zaimplementowanej w klasie (twoja klasa case Thing) do porównania equals.

 15
Author: Bhushan Bhangale,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-15 03:47:04

Ogólnie należy również nadpisać hashCode() za każdym razem, gdy nadpisujesz equals(), nawet jeśli tylko dla zwiększenia wydajności. HashCode() decyduje, do którego "wiadra" zostanie posortowany obiekt podczas porównywania, więc dwa obiekty, które equal() zostaną ocenione na true, powinny zwrócić to samo hashCode value(). Nie pamiętam domyślnego zachowania hashCode() (jeśli zwróci 0, to Twój kod powinien działać powoli, ale jeśli zwróci adres, to Twój Kod się nie powiedzie). Pamiętam kilka razy, kiedy mój kod nie powiódł się bo zapomniałem obejść hashCode(). :)

 12
Author: alexloh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-30 14:01:32

Używa metody equals na obiektach. Jeśli więc rzecz nie nadpisuje equals i nie użyje zmiennych przechowywanych w obiektach do porównania, nie zwróci true w metodzie contains().

 7
Author: Yishai,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-15 03:48:20
class Thing {  
    public int value;  

    public Thing (int x) {
        value = x;
    }

    equals (Thing x) {
        if (x.value == value) return true;
        return false;
    }
}

Musisz napisać:

class Thing {  
    public int value;  

    public Thing (int x) {
        value = x;
    }

    public boolean equals (Object o) {
    Thing x = (Thing) o;
        if (x.value == value) return true;
        return false;
    }
}

Teraz działa;)

 6
Author: Davide,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-10 08:16:39

Chciałem tylko zauważyć, że poniższa implementacja jest błędna, gdy value nie jest typem prymitywnym:

public class Thing
{
    public Object value;  

    public Thing (Object x)
    {
        this.value = x;
    }

    @Override
    public boolean equals(Object object)
    {
        boolean sameSame = false;

        if (object != null && object instanceof Thing)
        {
            sameSame = this.value == ((Thing) object).value;
        }

        return sameSame;
    }
}

W takim przypadku proponuję:

public class Thing {
    public Object value;  

    public Thing (Object x) {
        value = x;
    }

    @Override
    public boolean equals(Object object) {

        if (object != null && object instanceof Thing) {
            Thing thing = (Thing) object;
            if (value == null) {
                return (thing.value == null);
            }
            else {
                return value.equals(thing.value);
            }
        }

        return false;
    }
}
 6
Author: Caner,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-21 12:06:45

Inne plakaty odpowiedziały na pytanie, jak działa contains ().

Równie ważnym aspektem twojego pytania jest jak poprawnie zaimplementować equals (). A odpowiedź na to jest tak naprawdę zależna 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 oba mają x=5, czy są równe? To naprawdę zależy od tego, co próbujesz zrobić.

Jeśli interesuje Cię tylko równość obiektów, to Domyślna implementacja .equals () (ta dostarczana przez obiekt) używa tylko tożsamości (tzn. this = = other). Jeśli tego chcesz, to po prostu nie implementuj equals () na swojej klasie (niech dziedziczy od obiektu). Kod, który napisałeś, chociaż jest poprawny, jeśli dążysz do tożsamości, nigdy nie pojawi się w prawdziwej klasie b / c, nie zapewnia żadnej korzyści z używania domyślnego obiektu.implementacja equals ().

Jeśli dopiero zaczynasz z tymi rzeczami, zdecydowanie polecam Skuteczna Książka Java Joshua Bloch. 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)

 4
Author: Kevin Day,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-15 05:55:06

Skrót od JavaDoc :

boolean contains (Object o)

Zwraca true, jeśli ta lista zawiera określony element. Bardziej formalnie, zwraca true wtedy i tylko wtedy, gdy lista ta zawiera co najmniej jeden element e taki że (o = = null ? e = = null : o.equals (e))

 3
Author: DenisKolodin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-01 11:49:08