2010-01-26 9 views
-2

Les deux cartes c1 et c4 semblent être égales ... mais ce n'est pas la raison. Je veux qu'ils soient égaux pour qu'un seul d'entre eux soit autorisé dans le Set. : |Objet Java Egalité

import java.util.*; 
class Card2 
{ 
private int value; 
private String type; 

public Card2(int v,String t) 
{ 
    value=v; 
    type=t; 
} 

public int getValue() 
{ 
    return value; 
} 

public String getType() 
{ 
    return type; 
} 

public String toString() 
{ 
    return(type+" "+value); 
} 

public boolean equals(Object oo) 
{ 
    if(!(oo instanceof Card)) 
    return false; 

    Card cc=(Card) oo; 

    if(this.getValue()==cc.getValue() && this.getType().equals(cc.getType())) 
    return true; 
    else 
    return false; 
} 

public int hashCode() 
{ 
    return value; 
} 

public static void main(String args[]) 
{ 
    HashSet<Card> deck=new HashSet<Card>(); 

    Card c1=new Card(5,"Spade"); 

    Card c2=new Card(10,"Hearts"); 

    Card c3=c2; //Equal Ref card entity 

    Card c4=new Card(5,"Spade"); 

    System.out.println(c1.equals(c4)); 

    deck.add(c1); 
    deck.add(c2); 
    deck.add(c4); 
    deck.add(c3); 

    for(Card cc:deck) 
    System.out.println(cc); 
} 
} 
+4

Vous avez utilisé Card2 dans votre question, ne devrait-il pas être Card à la place? Il ne compile pas pour le moment. –

+1

System.out.println (c1.equals (c4)) renvoie true et seules deux cartes sont imprimées dans la boucle: Hearts 10 & Spade 5 (je cours le code en changeant Card2 en Card pour le réparer). Quel est le problème? – JuanZe

+5

juste fyi: 'if (...) renvoie true; sinon, revenez faux: «Pourquoi feriez-vous cela au lieu de« retour ... »? – KitsuneYMG

Répondre

1

Votre hashCode() est incompatible avec equals().

java.util.HashSet utilise hashCode. Vous devez implémenter hashCode() pour prendre en compte le type.

+2

Tout en prenant en compte le type lors de la production du hashCode() serait mieux, il n'est pas nécessaire d'être correct. En fait 'return 1;' serait une implémentation correcte (mais très, très mauvaise) 'hashCode()' pour une classe autonome. –

+1

Son hashCode() semble bien. hashCode() n'a pas besoin d'être le même que égal à(). Il suffit de satisfaire a.hashCode()! = B.hashCode() puis! A.equals (b). –

+2

Ou plus intuitivement: Si a.equals (b) alors a.hashCode() == b.hashCode() – Draemon

2

Ils sont égaux (une fois que vous fixer la faute de frappe en remplaçant Card2 par Card), votre sortie de programme est:

 
true 
Hearts 10 
Spade 5

Que vous attendiez-vous?

+0

En fait cela ne le corrige pas car il n'utilise même pas 'Card2' – cletus

+2

@cletus Remplacer les deux occurrences (déclaration de classe + constructeur) de "Card2" par "Carte" et vous obtiendrez un programme valide qui fonctionne. Pourriez-vous expliquer ce qui n'est pas réglé alors? – Jerome

+0

Il existe clairement une classe appelée 'Card' qu'il est réellement. Cela ne vous semble pas étrange de coller une compilation qui ne compile pas? Clairement, ça le fait. Peut-être que le nom «Card2» est un cadeau? Donc vous avez tort et votre vengeance downvote est immature et n'a pas sa place sur SO. – cletus

5

tout d'abord: vous appelé votre classe Card2 mais parler comme Card partout (. Y compris la méthode equals() Cette réponse suppose que vous remplacez toutes les instances de Card2 avec Card).

Vous avez défini equals() de manière à renvoyer true si la valeur et le type de la carte sont identiques.

c1 a une valeur de 5 et un type de Spade.

c4 a une valeur de 5 et un type de Spade.

Le look à peu près la même chose pour moi.

1

Quel est le problème? Sortie sur mon système est:

true 
Spade 5 
Hearts 10 

Ce qui semble être exactement ce que vous voulez.

1

méthode equals() est faux, essayez ceci:

public boolean equals(Object oo) 
{ 
    if(!(oo instanceof Card2)) 
    return false; 

    Card2 cc=(Card2) oo; 

    return this.getValue()==cc.getValue() && this.getType().equals(cc.getType()); 
} 

C'est, vous devez être cohérent dans votre utilisation de la carte et Card2.

Notez également que j'ai changé votre:

if(this.getValue()==cc.getValue() && this.getType().equals(cc.getType())) 
    return true; 
else 
    return false; 

à

return this.getValue()==cc.getValue() && this.getType().equals(cc.getType()); 

Comme il est plus court et évite la violation d'une checkstyle rule. La raison pour laquelle c'est une bonne idée est que cela complique le code puisque ce que vous dites est "si quelque chose est vrai, retourne vrai, sinon si c'est faux, retourne faux". Plutôt que de forcer le lecteur du code à élaborer ce que vous faites, vous pouvez simplement dire «retourner quelque chose» et l'utilisateur éventuel de votre code peut comprendre plus rapidement ce que vous faites.

+0

'Card2 cc = (Card2) oo;' pas 'Carte cc = ...' –

+0

@Carlos: Doh! Merci, et corrigé. –

+0

La règle checkstyle ne donne aucune raison. Je serais curieux de savoir s'il y a une raison. J'utilise parfois cet idiome (if() renvoie true, return false;) si je pense que cela rend le code plus clair (rarement). – Yishai

0

Une autre vérification d'égalité est manquante dans votre méthode equals(). Vérifiez si les objets eux-mêmes sont la même référence. C'est un court circuit lorsque vous comparez des choses comme "c2.equals (c3)".

0

Votre méthode Equals nécessite des améliorations. Vous devriez tester pour null et pour la similitude. En outre, l'utilisation de instanceof peut aboutir à ce que les égales deviennent non commutatives, si vous autorisez le sous-classement et implémentez des équations dans les deux classes. Par exemple si Card2 étend Card, et Card a un égal qui teste par exampleof Card, et Card2 écrase ceci avec un égal qui teste par exemple de Card2, alors pour une instance cc2 de classe Card2 et une autre instance cc de Card l'utilisation de instanceof signifie que cc.equals (cc2) est vrai, mais cc2.equals (cc) est faux, ce qui peut conduire à un comportement indésirable.

Vous pouvez effectuer les opérations suivantes:

public boolean equals(Object other) { 
    // null is not equal 
    if (null == other) 
     return false; 
    // same is equal 
    if (this == other) 
     return true; 
    // different class, not equal 
    if (other.getClass() != getClass()) 
     return false; 

Alternativement, si vous souhaitez autoriser subclassing, vous devez tester uniquement les propriétés qui sont superclasse. Donc, si la carte a une valeur, et Card2 étend la carte et a une valeur et le type, votre méthode equals ne devrait chercher carte instanceof et comparer uniquement les attributs de carte:

//if (other.getClass() != getClass()) 
    // return false; 
    if (!(other instanceof Card)) 
     return false; 
    card = (Card) other; 
    if (this.getValue() == card.getValue()) 
     return true; 
    return false; 
} 

Là encore, tout cela pourrait être sans aucun rapport avec votre problème.

+1

Rien de tout cela ne répond à sa question, il vérifie correctement la nullité, l'optimisation de la «similitude» n'est pas si importante dans le cas général, et les points plus fins de l'instance vs.getClass - * les deux * sont cassés dans certaines circonstances - ne sert qu'à le rendre plus confus. Je ne pense pas que ce soit une bonne réponse. –

0

Voici notre classe Card bien reçue d'un projet récent; J'espère que cela vous aidera. L '"état" est utilisé pour déterminer si la carte est dans le jeu, dans une main, etc. La valeur est de 1 à 14 avec 11 - 14 étant les cartes de visage (Jack, Queen, King, et As).