web-dev-qa-db-fra.com

HashSet ne semble pas réaliser que deux objets sont identiques.

J'essaie d'utiliser HashSet pour stocker des objets d'une classe que j'ai créée, mais apparemment les mêmes objets semblent avoir deux hachages différents, c'est pourquoi la méthode contains ne se rend pas compte que l'objet est déjà dans le HashSet. Cela conduit à mon programme à court de mémoire de tas.

Je ne pense pas que je fais quelque chose de mal, mais je voulais quand même un deuxième avis. J'ai fait des opérations similaires avant, tout fonctionnait bien, ce qui rend cela particulièrement ennuyeux. J'apprécierais toute aide.

Voici mon code

move1 = new Move(t,s);
if(move1.hashCode()==new Move(t,s).hashCode())
    System.out.println("match");
move2 = new Move(s,t);
moves.add(move1); 
moves.add(move2);
if(moves.contains(new Move(t,s)))
    System.out.println("match found");

Voici la classe Move:

public class Move {
    private int move1;
    private int move2;

    Move(int m1, int m2)
    {
        move1 = m1;
        move2 = m2;
    }

    public String toString()
    {
         return String.valueOf(move1)+" "+String.valueOf(move2);
    }
}

Voici la sortie que j'obtiens

Exception in thread "main" Java.lang.OutOfMemoryError: Java heap space
    at Java.util.HashMap.addEntry(HashMap.Java:797)
    at Java.util.HashMap.put(HashMap.Java:431)
    at Java.util.HashSet.add(HashSet.Java:194)
    at makeMove.<init>(makeMove.Java:33)
26
efficiencyIsBliss

Vous devez remplacer la méthode Object#hashCode() dans la classe Move pour lui permettre de renvoyer la même valeur hashCode() pour l'état de Move instance. N'oubliez pas de remplacer également Object#equals() .

Voir également:


Astuce : si vous utilisez un IDE comme Eclipse , vous pouvez aussi simplement cliquez sur quelque part dans la classe Move, choisissez Source> Generate hashCode () et equals (). Voici à quoi cela ressemble alors:

@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + move1;
    result = prime * result + move2;
    return result;
}

@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    Move other = (Move) obj;
    if (move1 != other.move1)
        return false;
    if (move2 != other.move2)
        return false;
    return true;
}
39
BalusC

HashSet déterminera l'égalité en fonction de l'appel de hashCode () et equals (). Vous ne les avez pas implémentés, vous les hériterez donc d'Object. Les méthodes hashCode et equals de Object sont basées uniquement sur la question de savoir si les références sont égales.

C'est pourquoi if(move1.hashCode()==new Move(t,s).hashCode()) est faux. move1 est une instance différente de l'instance créée en appelant new Move (t, s) .hashCode ()

Vous devrez implémenter hashCode et equals dans votre classe Move.

par exemple (bien que peut-être non optimal, et vous voudrez peut-être un égal nul nul - demandez à votre IDE de les générer si cela est possible)

public int hashCode() {
    return move1 ^ move2 +;
}

public boolean equals(Object o) {
  if(!other instanceof Move) 
      return false;

  Move other = (Move)o;

  return other.move1 == move1 && other.move2 == move2;
}
8
nos

Vous devez remplacer equals () and hasCode ()

Cela peut être une option.

import static Java.lang.System.out;
public class Move {
    private int move1;
    private int move2;

    Move(int m1, int m2) {
        move1 = m1;
        move2 = m2;
    }

    public String toString() {
         return String.valueOf(move1)+" "+String.valueOf(move2);
    }

    public int hashCode() {
        return move1 * 31 + move2 * 31;
    }
    public boolean equals( Object other ) {
        if( this == other ) { return true; }
        if( other instanceof Move ) {
            Move m2 = ( Move ) other;
            return this.move1 == m2.move1 && this.move2 == m2.move2;
        }
        return false;
    }

    public static void main( String  [] args ) {
        out.println( new Move(2,3).equals( new Move(2,3)));
        out.println( new Move(1,1).hashCode() == new Move(1,1).hashCode()  );
    }
}

Vous devez définir si l'ordre du déplacement est pertinent (1,2 est égal à 2,1 ou non)

Pour plus d'informations:

Quels problèmes doivent être pris en compte lors de la substitution d'equals et de hashCode en Java?

Point 8: toujours remplacer hashCode lorsque vous remplacez est égal à: "Java efficace" http://bit.ly/cd7uUl

1
OscarRyz