I am a high school student so I apologize for the terms I may misuse.
So I am making a slide puzzle game and working on the AI part. So I have a constructor that construct board and assign its hashcode such as 123456780. In my A* algorithm, I compare if the board that I generate (to find the solution) is already in the hashset. So I use contains method for it right? but how does the contains method works to check if the two boards are identical?.
public Board()
{
board = new int [3][3];
setPieces (board);
hashCode = generateHashCode ();
}
This is one of my constructor. In my board object, I have 2D array and the hashcode. But I wonder again, if the built-in contains method in Hash Set compare two boards hashcode. Or I need to write one.
Also, when I assign the hash code to a board, I should do it in my constructor right?
Thanks you
As you've discovered, you need to return a hashcode for your object in the overridden hashCode() method.
You can either compute a hashcode in that method, or compute it in the ctor and store it in a field, then return the field in the method override.
Any collection that uses the 'Hash' prefix has all objects contained within the collection stored in groups by their hashcode. So when you call a method like contains() the collection loops through each hashcode group and checks whether the hashcode of the object you parsed in matches the group. When a match is found, the objects within that hashcode group are checked using the equals() method of the stored object until an Object's equals() method returns true.
If you do not override the hashcode() method, then each Object subclass is given a more or less unique hashcode by the Object class implementation of the hashcode() method. This can cause some problems if you have already overridden the equals() method, because if two objects are considered equal the contains() method might still not find it if the hashcodes do not match.
The hashcode contract:
When implementing hashcode() the Java Object API has laid out a contract or a set of specifications on how you should implement the hashcode method. And they are;
If hashcode() is run on an object multiple times, it must always return the same number.
If two objects are considered equal by the equals() method then their hashcode() methods must return the same value.
If two objects have the same hashcode, they do not have to be considered equal by their equals() methods.
References:
The hashcode contract.
Implementing hashcode.
Related
When you read the description of hashCode() in the Object class, it says that
If two objects are equal according to the equals(Object) method, then
calling the hashCode method on each of the two objects must produce
the same integer result.
I've read an article and it says that an object's hashcode() can provide different integer values if it runs in different environments even though their content is the same.
It does not happen with String class's hashcode() because the String class's hashcode() creates integer value based on the content of the object. The same content always creates the same hash value.
However, it happens if the hash value of the object is calculated based on its address in the memory. And the author of the article says that the Object class calculates the hash value of the object based on its address in the memory.
In the example below, the objects, p1 and p2 have the same content so equals() on them returns true.
However, how come these two objects return the same hash value when their memory addresses are different?
Here is the example code: main()
Person p1 = new Person2("David", 10);
Person p2 = new Person2("David", 10);
boolean b = p1.equals(p2);
int hashCode1 = p1.hashCode();
int hashCode2 = p2.hashCode();
Here is the overriden hashcode()
public int hashCode(){
return Objects.hash(name, age);
}
Is the article's content wrong?
If there is a hashCode() that calculates a hash value based on the instance's address what is the purpose of them?
Also, if it really exists, it violates the condition that Object class's hashCode() specifies. How should we use the hashCode() then?
I think you have misunderstood this statement:
If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.
The word “must” means that you, the programmer, are required to write a hashCode() method which always produces the same hashCode value for two objects which are equal to each other according to their equals(Object) method.
If you don’t, you have written a broken object that will not work with any class that uses hash codes, particularly unsorted Sets and Maps.
I've read an article and it says that an object's hashcode() can provide different integer values if it runs in different environments even though their content is the same.
Yes, hashCode() can provide different values in different runtimes, for a class which does not override the hashCode() method.
… how come these two objects return the same hash value when their memory addresses are different?
Because you told them to. You overrode the hashCode() method.
If there is a hashCode() that calculates a hash value based on the instance's address what is the purpose of them?
It doesn’t have a lot of use. That’s why programmers are strongly recommended to override the method, unless they don’t care about object identity.
Also, if it really exists, it violates the condition that Object class's hashCode() specifies. How should we use the hashCode() then?
No it does not. The contract states:
Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.
As long as the hashCode method defined in the Object class returns the same value for the duration of the Java runtime, it is compliant.
The contract also says:
If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.
Two objects whose equals method reports that they are effectively equal must return the same hashCode. Any instance of the Object class whose type is not a subclass of Object is only equal to itself and cannot be equal to any other object, so any value it returns is valid, as long as it is consistent throughout the life of the Java runtime.
The article is wrong, memory address is not involved (btw. the address can change during the lifecycle of objects, so it's abstracted away as a reference). You can look at the default hashCode as a method that returns a random integer, which is always the same for the same object.
Default equals (inherited from Object) works exactly like ==. Since there is a condition (required for classes like HashSet etc. to work) that states when a.equals(b) then a.hashCode == b.hashCode, then we need a default hashCode which only has to have one property: when we call it twice, it must return the same number.
The default hashCode exists exactly so that the condition you mention is upheld. The value returned is not important, it's only important that it never changes.
No p1 and p2 does not have the same content
If you do p1.equals(p2) that will be false, so not the same content.
If you want p1 and p2 to equal, you need to implement the equals methods from object, in a way that compare their content. And IF you implement the equals method, then you also MUST implement the hashCode method, so that if equals return true, then the objects have the same hashCode().
Here's the design decision every programmer needs to make for objects they define of (say) MyClass:
Do you want it to be possible for two different objects to be "equal"?
If you do, then firstly you have to implement MyClass.equals() so that it gives the correct notion of equality for your purposes. That's entirely in your hands.
Then you're supposed to implement hashCode such that, if A.equals(B), then A.hashCode() == B.hashCode(). You explicitly do not want to use Object.hashCode().
If you don't want different objects to ever be equal, then don't implement equals() or hashCode(), use the implementations that Object gives you. For Object A and Object B (different Objects, and not subclasses of Object), then it is never the case that A.equals(B), and so it's perfectly ok that A.hashCode() is never the same as B.hashCode().
I have a quick question about TreeSet collections and hashCode methods. I have a TreeSet and I'm adding objects to it, before I add an object, I check to see if it exists in the TreeSet using the contains method.
I have 2 distinct objects, each of which produce a distinct hashCode using my implementation of the hashCode method, example below:
public int hashCode()
{
int hash = 7;
hash = hash * 31 + anAttribute.hashCode();
hash = hash * 31 + anotherAttribute.hashCode();
hash = hash * 31 + yetAnotherAttribute.hashCode();
return hash;
}
The hashCodes for a particular run are: 76126352 and 76126353 (the objects only differ by one digit in one attribute).
The contains method is returning true for these objects, even though the hashCodes are different. Any ideas why? This is really confusing and help would really be appreciated.
TreeSet does not use hashCode at all. It uses either compareTo or the Comparator you passed to the constructor. This is used by methods like contains to find objects in the set.
So the answer to your question is that your compareTo method or your Comparator are defined so that the two objects in question are considered equal.
From the javadocs:
a TreeSet instance performs all
element comparisons using its
compareTo (or compare) method, so two
elements that are deemed equal by this
method are, from the standpoint of the
set, equal.
From Java Doc:
If two objects are equal according to the equals(Object) method,
then calling the hashCode method on each of the two objects must
produce the same integer result.
Means: the objects you use for hashing are not equal.
You need to read Joshua Bloch's "Effective Java" chapter 3. It explains the equals contract and how to properly override equals, hashCode, and compareTo.
You don't need to checked if it is contained, because the insert() basically does the same operation (i.e. searching the proper position) on its way to the insertion point. If the object can't be inserted (i.e., the object is already contained), insert returns false.
I've made a Java class in which I simulate a Polynome (it contains an ArrayList<Pairs>, each pair has its own coefficient and exponent). But now I like to compare two Polynome's with the equals() method (with an Object).
I know I can't say that this == that because this will only compare the Polynome references. SO now I wondered if there's an easy way to compare both Polynome's values, or do I just have to check the first Pair of the first Polynome to the first Pair of the second Polynome etc.?
You have to override the equals() method of your Pair class to return true if and only if both the coefficient and the exponent are equal.
You should also override the hashCode() method if you override equals(). Although strictly speaking this isn't mandatory while you're using ArrayLists, it is good practice to always override equals() and hashCode() together.
Also note that because you're using a List, where the order of elements matters, x3+2x-1 won't be equal to 2x-1+x3, which is probably not what you want to see. You should store your Pair objects in a Set instead, as their equals() doesn't rely on the order in which you added the elements to them.
You have to override equals and check each and every Monomial in the Polynomial collection.
Hint: I'd have two classes - Monomial, with its own equals and hashCode, and a separate Polynomial, which would have a Set of Monomials and its own equals and hashCode.
I'm revising for my upcoming exam and I've came across a question from a past paper that I'm unsure on.
The question is the following : Describe the equivalence relation that the Object equals method implements. What relationship must hold between the Object equals method and hasCode methods?
If this came up in the exam then I wouldn't be too sure how about answering this. I'll try and give it my best shot. Since the Object equals method is checking whether two objects are equal, the hashcode gives objects ascii values. If you have two objects that are the same it is possible that they can be given the same hascode since they're equal. The object equals method you are told whether they're equal whereas the hashcode method gives you a value which you can then use to compare with other hashcodes and find out whether they're the same or not. Also could have I of mentioned something about overriding methods ? I'm not if that could come into play in the answer.
My answer is probably completely wrong but the best I could think off :P
To the Java API Documentation! especially Object.hashCode
If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.
This means that if the equal method returns true, hashCode must return the same value for both objects.
x.equals(y) == true => x.hashCode() == y.hashCode()
It is not required that if two objects are unequal according to the equals(java.lang.Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables.
But! If the objects are not the same they may have the same hashCode()! (But it is not advised)
The requirements for the equals() method are well described, so i won't repeat them here.
The question is clearly answered in the descriptions of both the equals() method and the hashCode() method. Have a look at equals method description and hashCode method description.
Here is the relevant answer you might be looking for:
The equals method for class Object implements the most discriminating
possible equivalence relation on objects; that is, for any non-null
reference values x and y, this method returns true if and only if x
and y refer to the same object (x == y has the value true).
Note that it is generally necessary to override the hashCode method
whenever this method is overridden, so as to maintain the general
contract for the hashCode method, which states that equal objects must
have equal hash codes.
This the hashCode method description:
If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.
Also, the hashCode method does not give the ASCII value of an object, merely an integer value that uniquely defines the object.
I found this comment on can StringBuffer objects be keys in TreeSet in Java?
"There are 2 identifying strategies used with Maps in Java (more-or-less).
Hashing: An input "Foo" is converted into a best-as-possible attempt to generate a number that uniquely accesses an index into an array. (Purists, please don't abuse me, I am intentionally simplifying). This index is where your value is stored. There is the likely possibility that "Foo" and "Bar" actually generate the same index value meaning they would both be mapped to the same array position. Obviously this can't work and so that's where the "equals()" method comes in; it is used to disambiguate
Comparison: By using a comparative method you don't need this extra disambiguation step because comparison NEVER produces this collision in the first place. The only key that "Foo" is equal to is "Foo". A really good idea though is if you can is to define "equals()" as compareTo() == 0; for consistency sake. Not a requirement."
my question is as follows:
if my class implements comparable, then does it mean I dont have to override equals and hashcode method for using my objects as keys in Hash collections. eg
class Person implements Comparable<Person> {
int id;
String name;
public Person(int id, String name) {
this.id=id;
this.name=name;
}
public int compareTo(Person other) {
return this.id-other.id;
}
}
Now, can I use my Person objects in Hashable collections?
The article you brough is talking on TreeSet. a tree set is a tree with each node has a place defined by it's value in compare to the other values already in the tree.
a hashTable stores key/value pairs in a hash table. When using a Hashtable, you specify an object that is used as a key, and the value that you want linked to that key. The key is then hashed, and the resulting hash code is used as the index at which the value is stored within the table.
the difference between Hashable and TreeSet is that treeset don't need hashCode, it just need to know if you need the take the item left or right in the tree. for that you can use Compare and nothing more.
in hashTable a compare will suffice, because it's build differently, each object get to his cell by hashing it, not by comparing it to the items already in the collection.
so the answer is no, you can' use Person in hashtable just with compareTo. u must override hashCode() and equals() for that
i also suggest you read this article on hashtables
HashTable does use equals and hashCode. Every class has those methods. If you don't implement them, you inherit them.
Whether you need to implement them depends on whether the inherited version is suitable for your purposes. In particular, since Person has no specified superclass, it inherits the Object methods. That means a Person object is equal only to itself.
Do you need two distinct Person objects to be treated as being equal as HashTable keys?
if my class implements comparable, then does it mean I dont have to override equals and hashcode method for using my objects as keys in Hash collections. eg
No, you still need to implement equals() and hashCode(). The methods perform very different functions and cannot be replaced by compareTo().
equals() returns a boolean based on equality of the object. This is usually identity equality and not field equality. This can be very different from the fields used to compare an object in compareTo(...) although if it makes sense for the entity, the equals() method can be:
#Overrides
public boolean equals(Object obj) {
if (obj == null || obj.getClass() != getClass()) {
return false;
} else {
return compareTo((Person)obj) == 0;
}
}
hashCode() returns an integer value for the instance which is used in hash tables to calculate the bucket it should be placed in. There is no equivalent way to get this value out of compareTo(...).
TreeSet needs Comparable, to add values to right or left of tree. HashMap needs equals() and Hashcode() methods that are available from Object Class but you have to override them for your purpose.
If a class implements Comparable, that would suggest that instances of the class represent values of some sort; generally, when classes encapsulate values it will be possible for there to exist two distinct instances which hold the same value and should consequently be considered equivalent. Since the only way for distinct object instances to be considered equivalent is for them to override equals and hashCode, that would imply that things which implement Comparable should override equals and hashCode unless the encapsulated values upon which compare operates will be globally unique (implying that distinct instances should never be considered equivalent).
As a simple example, suppose a class includes a CreationRank field of type long; every time an instances is created, that member is set to a value fetched from a singleton AtomicLong, and Comparable uses that field to rank objects in the order of creation. No two distinct instances of the class will ever report the same CreationRank; consequently, the only way x.equals(y) should ever be true is if x and y refer to the same object instance--exactly the way the default equals and hashCode work.
BTW, having x.compare(y) return zero should generally imply that x.equals(y) will return true, and vice versa, but there are some cases where x.equals(y) may be false but x.compare(y) should nonetheless return zero. This may be the case when an object encapsulates some properties that can be ranked and others that cannot. Consider, for example, a hypohetical FutureAction type which encapsulates a DateTime and an implementation of a DoSomething interface. Such things could be ranked based upon the encapsulated date and time, but there may be no sensible way to rank two items which have the same date and time but different actions. Having equals report false while compare reports zero would make more sense than pretending that the clearly-non-equivalent items should be called "equal".