web-dev-qa-db-fra.com

Méthode Contains personnalisée d'ArrayList

J'ai un objet

class A {
  private Long id; 
  private String name; 
  public boolean equals(Long v) {
     return this.id.equals(v);
  }
}

et ArrayList de ces objets. Ce que je veux, c'est pouvoir vérifier si cette liste contient un champ objet par objet. Par exemple:

ArrayList<A> list = new ArrayList<A>(); if (list.contains(0L)) {...}

mais la méthode Equals remplacée ne m'aide pas. Qu'est ce que je fais mal? Je vous remercie

UPDATE Et dois-je aussi remplacer une méthode hashcode ()?

29
nKognito

voici un code qui pourrait montrer comment cela fonctionne:

import Java.util.ArrayList;

class A {
  private Long id; 
  private String name; 

  A(Long id){
      this.id = id;
  }

    @Override
  public boolean equals(Object v) {
        boolean retVal = false;

        if (v instanceof A){
            A ptr = (A) v;
            retVal = ptr.id.longValue() == this.id;
        }

     return retVal;
  }

    @Override
    public int hashCode() {
        int hash = 7;
        hash = 17 * hash + (this.id != null ? this.id.hashCode() : 0);
        return hash;
    }
}

public class ArrayList_recap {
    public static void main(String[] args) {
        ArrayList<A> list = new ArrayList<A>(); 

        list.add(new A(0L));
        list.add(new A(1L));

        if (list.contains(new A(0L)))
        {
            System.out.println("Equal");
        }
        else
        {
            System.out.println("Nah.");
        }    
    }

}

Tout d'abord, il y a un remplacement de la méthode equals (Object o). Ensuite, il y a également le remplacement de hashCode (). Notez également que l'instance d'une vérification dans les égaux garantira que vous n'essayez pas de comparer différents objets.

Cela devrait faire l'affaire! J'espère que cela a aidé! À votre santé :)

48
Vern

Vous n'avez pas remplacé la méthode dans votre classe. Pour remplacer, les paramètres de méthode doivent également être du même type.

ça devrait être

public boolean equals(Object o) {

}

où comme dans votre cas c'est

public boolean equals(Long o) {

 }

vous devez probablement le faire

public boolean equals(Object o)
    {
        if (o == null) return false;
        if (o == this) return true; //if both pointing towards same object on heap

            A a = (A) o;
        return this.id.equals(a.id);
    }
8
Zohaib

Qu'est ce que je fais mal?

Vous ne dérogez pas. Vous surchargez.

La méthode contains appelle la méthode equals avec la signature equals(Object), donc cette (nouvelle) méthode que vous avez ajoutée ne sera pas appelée.

L'autre problème est que votre méthode equals a la mauvaise sémantique pour contains. La méthode contains doit comparer this avec un objet qui pourrait être membre de la liste. Votre liste ne contient pas d'objets Long. Il contient des objets de type A.

Maintenant, vous pourriez vous en sortir ... si vous utilisez des types de liste bruts ... mais ce que vous essayez de faire est une violation du contrat API et de mauvaises pratiques. Une meilleure solution est d'itérer et de tester explicitement les éléments de la liste.


Et dois-je remplacer une méthode hashcode () aussi?

Si vous remplacez equals(Object) alors vous devez également remplacer hashcode().

Cela ne fera aucune différence ici, mais c'est essentiel si vous mettez vos objets A dans des structures de données hachées. Et puisque vous ne savez pas ce que le prochain gars va faire avec votre code, il est recommandé de vous assurer que equals(Object) et hashCode() ont une sémantique compatible.

7
Stephen C