web-dev-qa-db-fra.com

Comment une méthode contient () ArrayList évalue-t-elle les objets?

Supposons que je crée un objet et que je l'ajoute à mon ArrayList. Si je crée ensuite un autre objet avec exactement la même entrée de constructeur, la méthode contains() évaluera-t-elle que les deux objets sont identiques? Supposons que le constructeur ne fasse rien de drôle avec l'entrée et que les variables stockées dans les deux objets sont identiques.

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

Est-ce ainsi que la class devrait être implémentée pour que contains() renvoie true?

288
Mantas Vidutis

ArrayList implements l'interface de liste.

Si vous examinez la méthode Javadoc pour List dans la méthode contains, vous verrez qu'elle utilise la méthode equals() pour évaluer si deux objets sont identiques.

323
Binary Nerd

Je pense que les bonnes implémentations devraient être

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

ArrayList utilise la méthode equals implémentée dans la classe (votre classe Thing case) pour effectuer la comparaison equals.

15
Bhushan Bhangale

En règle générale, vous devez également remplacer hashCode() à chaque fois que vous remplacez equals(), même si ce n'est que pour améliorer les performances. HashCode() décide dans quel "compartiment" votre objet est trié lors de la comparaison. Ainsi, deux objets que equal() considère comme vrais doivent renvoyer le même hashCodevalue(). Je ne me souviens pas du comportement par défaut de hashCode() (s'il renvoie 0, votre code devrait fonctionner lentement mais s'il renvoie l'adresse, votre code échouera). Je me souviens de nombreuses fois où mon code a échoué parce que j'avais oublié de remplacer hashCode(). :)

11
alexloh

Il utilise la méthode equals sur les objets. Ainsi, à moins que Thing ne supprime des valeurs égales et utilise les variables stockées dans les objets à des fins de comparaison, il ne retournera pas true sur la méthode contains().

7
Yishai

Je voulais juste noter que l'implémentation suivante est fausse quand value n'est pas un type primitif:

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

Dans ce cas, je propose ce qui suit:

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;
    }
}
5
Caner
class Thing {  
    public int value;  

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

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

Vous devez écrire:

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

Maintenant ça marche ;)

5
Davide

D'autres affiches ont abordé la question de savoir comment contient () fonctionne.

Un aspect tout aussi important de votre question est de savoir comment implémenter correctement equals (). Et la réponse à cette question dépend vraiment de ce qui constitue l'égalité d'objet pour cette classe particulière. Dans l'exemple que vous avez fourni, si vous avez deux objets différents pour lesquels x = 5, sont-ils égaux? Cela dépend vraiment de ce que vous essayez de faire.

Si vous ne vous intéressez qu'à l'égalité des objets, alors l'implémentation par défaut de .equals () (celle fournie par Object) utilise uniquement l'identité (c'est-à-dire ceci == autre). Si c'est ce que vous voulez, alors n'implémentez pas equals () sur votre classe (laissez-la hériter de Object). Le code que vous avez écrit, bien que correct si vous voulez une identité, n'apparaîtra jamais dans une vraie classe b/c, il ne fournit aucun avantage par rapport à l'utilisation de l'implémentation Object.equals () par défaut.

Si vous commencez à peine avec ce matériel, je vous recommande vivement le livre Effective Java de Joshua Bloch. C'est une excellente lecture, et couvre ce genre de chose (plus comment implémenter correctement equals () lorsque vous essayez de faire plus que des comparaisons basées sur l'identité)

4
Kevin Day

Raccourci de JavaDoc :

boolean contient (Object o)

Renvoie true si cette liste contient l'élément spécifié. Plus formellement, renvoie vrai si et seulement si cette liste contient au moins un élément e tel que (o == null? E == null: o.equals (e))

2
DenisKolodin