5 Replies - 1234 Views - Last Post: 05 June 2007 - 07:52 AM Rate Topic: -----

#1 TwoSpots  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 45
  • Joined: 02-February 07

Override Object.equals and Object.hashCode

Posted 04 June 2007 - 01:18 PM

Hello, ÖIím required to Override Object.equals in my Card class so that it compares suit then face-value. And Override Object.hashCode in the manner suggested by the library API when a class overrides equals.

Once again I understand what the question is asking and why however, I need help with the implementation. Do I modify the existing method or define another? How many Object.equals methods can you define in a single class?

Any pointers would surely be appreciated. Hereís my Card Class:
//--------------------------------------------------------------------------------------
import java.util.*;
import java.util.ArrayList;
import java.util.HashMap;
//--------------------------------------------------------------------------------------
/**
  A <code>Card</code> object represents a playing card, such as "Ace of Hearts". A card has 
  a suit(Diamond, Heart, Spade or Club) and a face-value(2,...10, 11 = Jack, 12 = Queen, 13 = king). 
  A card object is immutable; once instantiated, the values cannot change.
*/
public class Card 
{	
	// card's face-value and suit
	private int faceValue, suit;
   
	/** String representation of card suits - position in array indicates corresponding integral value */ 
	public static final String[] FACE_VALUE = {"", "", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Jack", "Queen", "King", "Ace"};
	public static final String[] SUIT	   = {"Clubs", "Diamonds", "Hearts", "Spades"};				
//--------------------------------------------------------------------------------------   	
  /** Creates a new Card instance, in * "uninitialized" state (requiring face and value settings).*/ 	
	public Card(){
		this.faceValue = -1; 
		this.suit	  = -1;
	}	   	 	
//--------------------------------------------------------------------------------------   	
   	/** 
   	  Creates a new Card instance and calls the setters.
   	  @param face the card's face-value.
   	  @param suit the card's suit. 
   	*/ 
   	public Card(int cardFaceValue, int cardSuit){
		setFaceValue(cardFaceValue);
		setSuit(cardSuit);
	}  
//--------------------------------------------------------------------------------------
   	/** 
   	  Returns the card's face-value. 
	  @return faceValue the card's face-value.
	*/
	public int getFaceValue() {return this.faceValue;}   
//--------------------------------------------------------------------------------------
	/** 
	  Updates the card's face-value. 
	  @param fv the card's face-value.
	*/
	public void setFaceValue(int fv){
		if(fv >= 2 && fv <= 14)this.faceValue = fv;
		else this.faceValue = -1; 
	}	
//--------------------------------------------------------------------------------------
   	/** 
   	  Returns the card's suit. 
	  @return suit the card's suit.
	*/
	public int getSuit() {return this.suit;}
//--------------------------------------------------------------------------------------
	/** 
	  Updates the card's suit. 
	  @param s the card's suit.
	*/
	public void setSuit(int s){
		if(s >= 0 && s <= 3)this.suit = s;
		else this.suit = -1;
	}
//----------------------------- Overridden Object methods ------------------------------
	/**  
	  Returns a string representation of the card's faceValue and suit.
	  @return a string representation of card's faceValue and suit(i.e. Two of Hearts) 
	*/		
	public String toString () 
	{return(faceValue == -1 || suit == -1) ? "Unitialized Card" : (FACE_VALUE[faceValue] + " of " + SUIT[suit]);} 		
//-------------------------------------------------------------------------------------- 
	public boolean equals(Object o){ 
		boolean eq = false; 
		if (o instanceof Card) 
		{ 
			Card c = (Card) o; 
			eq = this.faceValue == c.faceValue && this.suit == c.suit; 
		} 
		return eq; 
	} 
//--------------------------------------------------------------------------------------
	public int hashCode (){return FACE_VALUE.length * suit + faceValue;} 
//--------------------------------------------------------------------------------------
}	



Is This A Good Question/Topic? 0
  • +

Replies To: Override Object.equals and Object.hashCode

#2 William_Wilson  Icon User is offline

  • lost in compilation
  • member icon

Reputation: 205
  • View blog
  • Posts: 4,807
  • Joined: 23-December 05

Re: Override Object.equals and Object.hashCode

Posted 04 June 2007 - 01:23 PM

all that is required is that you declare the method yourself within the class which overrides it. Thus instead of Card.equals(Object) calling the Object method, it will call yours in class Card, as Java always looks locally first.

You should only implement 1, which is:
public boolean equals(Card o)

thus you compare all variables within both Card objects if they match return true, otherwise false
Was This Post Helpful? 0
  • +
  • -

#3 TwoSpots  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 45
  • Joined: 02-February 07

Re: Override Object.equals and Object.hashCode

Posted 04 June 2007 - 03:20 PM

Hello William,

Hereís what Iíve implemented for the Object.equals and Object.hashCode methods:

//--------------------------------------------------------------------------------------
public boolean equals(Object otherObject){ 
	if(this == otherObject) return true;
	if(otherObject == null) return false;
	if(getClass() != otherObject.getClass()) return false;
	Card other = (Card)otherObject;
	return suit == other.suit && faceValue == other.faceValue;
}	
//--------------------------------------------------------------------------------------
public int hashCode (){return FACE_VALUE.length * new Double(suit).hashCode() + SUIT.length * new Double(faceValue).hashCode();}



Iím assuming that Iíve compared suit (first) then face-value in the equals method and arbitrarily chose the array lengths (FACE_VALUE.length) to multiple the field values with (not knowing what to multiple them with). Is there any convention that I should apply to the hashCode method?

Thanks.
Was This Post Helpful? 0
  • +
  • -

#4 oubless  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 24
  • Joined: 28-May 07

Re: Override Object.equals and Object.hashCode

Posted 05 June 2007 - 06:48 AM

View PostTwoSpots, on 4 Jun, 2007 - 03:20 PM, said:

Hello William,

Hereís what Iíve implemented for the Object.equals and Object.hashCode methods:

//--------------------------------------------------------------------------------------
public boolean equals(Object otherObject){ 
	if(this == otherObject) return true;
	if(otherObject == null) return false;
	if(getClass() != otherObject.getClass()) return false;
	Card other = (Card)otherObject;
	return suit == other.suit && faceValue == other.faceValue;
}	
//--------------------------------------------------------------------------------------
public int hashCode (){return FACE_VALUE.length * new Double(suit).hashCode() + SUIT.length * new Double(faceValue).hashCode();}



Iím assuming that Iíve compared suit (first) then face-value in the equals method and arbitrarily chose the array lengths (FACE_VALUE.length) to multiple the field values with (not knowing what to multiple them with). Is there any convention that I should apply to the hashCode method?

Thanks.

There is a specific difference between instanceof and getClass() !=getClass()
comparing Class objects with != or == can lead to hard to track issues...
-In case your class is extended this check will always return false -> you might want it to return true under some conditions
-If you need classes compared use getClass().equals(obj.getClass()) instead of ==
All this can be written like this:
public boolean equals(Object otherObject){ 
	return ( this == otherObject ) ||
		( 
			  otherObject != null &&
			  this.getClass().equals( otherObject.getClass() ) &&
			  this.suit == ( (Card)otherObject ).suit && 
			  faceValue ==  ( (Card)otherObject ).faceValue
		);
}	


Was This Post Helpful? 0
  • +
  • -

#5 TwoSpots  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 45
  • Joined: 02-February 07

Re: Override Object.equals and Object.hashCode

Posted 05 June 2007 - 07:45 AM

Great thanks, Iíll be sure to use getClass().equals(obj.getClass()) instead of == when comparing classes.

Aside, Iím still not clear on how to implement the hashCode(). I canít seem to find a decent example and explanation to what is required in the definition.

Hereís what Iíve produced:

public int hashCode (){return FACE_VALUE.length * new Double(suit).hashCode() + SUIT.length * new Double(faceValue).hashCode();}


Was This Post Helpful? 0
  • +
  • -

#6 William_Wilson  Icon User is offline

  • lost in compilation
  • member icon

Reputation: 205
  • View blog
  • Posts: 4,807
  • Joined: 23-December 05

Re: Override Object.equals and Object.hashCode

Posted 05 June 2007 - 07:52 AM

it is not for classes, the getClass() method returns a String, which needs to be compared character by character, instead of literally since the address location of each physical String is not the same, and thus false.

if your suits are stored as ints (1-4), then a possible hashcode could simply be:
a cards face value * a cards suit, these would be guaranteed to be unique
if you use (0-3) then you must add 1 to the suit first.
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1