Internal implementation of java.util.HashMap and HashSet - java

I have been trying to understand the internal implementation of java.util.HashMap and java.util.HashSet.
Following are the doubts popping in my mind for a while:
Whats is the importance of the #Override public int hashcode() in a HashMap/HashSet? Where is this hash code used internally?
I have generally seen the key of the HashMap be a String like myMap<String,Object>. Can I map the values against someObject (instead of String) like myMap<someObject, Object>? What all contracts do I need to obey for this happen successfully?
Thanks in advance !
EDIT:
Are we saying that the hash code of the key (check!) is the actual thing against which the value is mapped in the hash table? And when we do myMap.get(someKey); java is internally calling someKey.hashCode() to get the number in the Hash table to be looked for the resulting value?
Answer: Yes.
EDIT 2:
In a java.util.HashSet, from where is the key generated for the Hash table? Is it from the object that we are adding eg. mySet.add(myObject); then myObject.hashCode() is going to decide where this is placed in the hash table? (as we don't give keys in a HashSet).
Answer: The object added becomes the key. The value is dummy!

The answer to question 2 is easy - yes you can use any Object you like. Maps that have String type keys are widely used because they are typical data structures for naming services. But in general, you can map any two types like Map<Car,Vendor> or Map<Student,Course>.
For the hashcode() method it's like answered before - whenever you override equals(), then you have to override hashcode() to obey the contract. On the other hand, if you're happy with the standard implementation of equals(), then you shouldn't touch hashcode() (because that could break the contract and result in identical hashcodes for unequal objects).
Practical sidenote: eclipse (and probably other IDEs as well) can auto generate a pair of equals() and hashcode() implementation for your class, just based on the class members.
Edit
For your additional question: yes, exactly. Look at the source code for HashMap.get(Object key); it calls key.hashcode to calculate the position (bin) in the internal hashtable and returns the value at that position (if there is one).
But be careful with 'handmade' hashcode/equals methods - if you use an object as a key, make sure that the hashcode doesn't change afterwards, otherwise you won't find the mapped values anymore. In other words, the fields you use to calculate equals and hashcode should be final (or 'unchangeable' after creation of the object).
Assume, we have a contact with String name and String phonenumber and we use both fields to calculate equals() and hashcode(). Now we create "John Doe" with his mobile phone number and map him to his favorite Donut shop. hashcode() is used to calculate the index (bin) in the hash table and that's where the donut shop is stored.
Now we learn that he has a new phone number and we change the phone number field of the John Doe object. This results in a new hashcode. And this hashcode resolves to a new hash table index - which usually isn't the position where John Does' favorite Donut shop was stored.
The problem is clear: In this case we wanted to map "John Doe" to the Donut shop, and not "John Doe with a specific phone number". So, we have to be careful with autogenerated equals/hashcode to make sure they're what we really want, because they might use unwanted fields, introducing trouble with HashMaps and HashSets.
Edit 2
If you add an object to a HashSet, the Object is the key for the internal hash table, the value is set but unused (just a static instance of Object). Here's the implementation from the openjdk 6 (b17):
// Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object();
private transient HashMap<E,Object> map;
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}

Hashing containers like HashMap and HashSet provide fast access to elements stored in them by splitting their contents into "buckets".
For example the list of numbers: 1, 2, 3, 4, 5, 6, 7, 8 stored in a List would look (conceptually) in memory something like: [1, 2, 3, 4, 5, 6, 7, 8].
Storing the same set of numbers in a Set would look more like this: [1, 2] [3, 4] [5, 6] [7, 8]. In this example the list has been split into 4 buckets.
Now imagine you want to find the value 6 out of both the List and the Set. With a list you would have to start at the beginning of the list and check each value until you get to 6, this will take 6 steps. With a set you find the correct bucket, the check each of the items in that bucket (only 2 in our example) making this a 3 step process. The value of this approach increases dramatically the more data you have.
But wait how did we know which bucket to look in? That is where the hashCode method comes in. To determine the bucket in which to look for an item Java hashing containers call hashCode then apply some function to the result. This function tries to balance the numbers of buckets and the number of items for the fastest lookup possible.
During lookup once the correct bucket has been found each item in that bucket is compared one at a time as in a list. That is why when you override hashCode you must also override equals. So if an object of any type has both an equals and a hashCode method it can be used as a key in a Map or an entry in a Set. There is a contract that must be followed to implement these methods correctly the canonical text on this is from Josh Bloch's great book Effective Java: Item 8: Always override hashCode when you override equals

Whats is the importance of the #Override public int hashcode() in a HashMap/HashSet?
This allows the instance of the map to produce a useful hash code depending on the content of the map. Two maps with the same content will produce the same hash code. If the content is different, the hash code will be different.
Where is this hash code used internally?
Never. This code only exists so you can use a map as a key in another map.
Can I map the values against someObject (instead of String) like myMap<someObject, Object>?
Yes but someObject must be a class, not an object (your name suggests that you want to pass in object; it should be SomeObject to make it clear you're referring to the type).
What all contracts do I need to obey for this happen successfully?
The class must implement hashCode() and equals().
[EDIT]
Are we saying that the hash code of the key (check!) is the actual thing against which the value is mapped in the hash table?
Yes.

Yes. You can use any object as the key in a HashMap. In order to do so following are the steps you have to follow.
Override equals.
Override hashCode.
The contracts for both the methods are very clearly mentioned in documentation of java.lang.Object. http://java.sun.com/javase/6/docs/api/java/lang/Object.html
And yes hashCode() method is used internally by HashMap and hence returning proper value is important for performance.
Here is the hashCode() method from HashMap
public V put(K key, V value) {
if (key == null)
return putForNullKey(value);
int hash = hash(key.hashCode());
int i = indexFor(hash, table.length);
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
modCount++;
addEntry(hash, key, value, i);
return null;
}
It is clear from the above code that hashCode of each key is not just used for hashCode() of the map, but also for finding the bucket to place the key,value pair. That is why hashCode() is related to performance of the HashMap

Any Object in Java must have a hashCode() method; HashMap and HashSet are no execeptions. This hash code is used if you insert the hash map/set into another hash map/set.
Any class type can be used as the key in a HashMap/HashSet. This requires that the hashCode() method returns equal values for equal objects, and that the equals() method is implemented according to contract (reflexive, transitive, symmetric). The default implementations from Object already obey these contracts, but you may want to override them if you want value equality instead of reference equality.

There is a intricate relationship between equals(), hashcode() and hash tables in general in Java (and .NET too, for that matter). To quote from the documentation:
public int hashCode()
Returns a hash code value for the object. This method is supported for the benefit of hashtables such as those provided by java.util.Hashtable.
The general contract of hashCode is:
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.
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.
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 hashtables.
As much as is reasonably practical, the hashCode method defined by class Object does return distinct integers for distinct objects. (This is typically implemented by converting the internal address of the object into an integer, but this implementation technique is not required by the Java™ programming language.)
The line
#Overrides public int hashCode()
just tells that the hashCode() method is overridden. This ia usually a sign that it's safe to use the type as key in a HashMap.
And yes, you can aesily use any object which obeys the contract for equals() and hashCode() in a HashMap as key.

In answer to question 2, though you can have any class that can be used to as the key in Hashmap, the best practice is to use immutable classes as keys for the HashMap. Or at the least if your "hashCode", and "equals" implementation are dependent on some of the attributes of your class then you should take care that you don't provide methods to alter these attributes.

Aaron Digulla is absolutely correct. An interesting additional note that people don't seem to realise is that the key object's hashCode() method is not used verbatim. It is, in fact, rehashed by the HashMap i.e. it calls hash(someKey.hashCode)), where hash() is an internal hashing method.
To see this, have a look at the source: http://kickjava.com/src/java/util/HashMap.java.htm
The reason for this is that some people implement hashCode() poorly and the hash() function gives a better hash distribution. It's basically done for performance reasons.

HashCode method for collection classes like HashSet, HashTable, HashMap etc – Hash code returns integer number for the object that is being supported for the purpose of hashing. It is implemented by converting internal address of the object into an integer. Hash code method should be overridden in every class that overrides equals method.
Three general contact for HashCode method
For two equal objects acc. to equal method, then calling HashCode for both object it should produce same integer value.
If it is being called several times for a single object, then it should return constant integer value.
For two unequal objects acc. to equal method, then calling HashCode method for both object, it is not mandatory that it should produce distinct value.

Related

what is the disadvantage of overriding equals and not hashcode and vice versa? [duplicate]

This question already has answers here:
Why do I need to override the equals and hashCode methods in Java?
(31 answers)
Closed 7 years ago.
I know there are lots of similar questions out there but I have not satisfied by the answers I have read. I tried to figure it out but I still did not get the idea.
What I know is these two are important while using set or map especially HashSet, HashMap or Hash objects in general which use hash mechanism for storing element objects.
Both methods are used to test if two Objects are equal or not.
For two objects A and B to be equal first they need to have the same hash value( have to be in the same bucket) and second we have to get true while executing A.equals(B).
What I do not understand is, WHY is it necessary to override both of these methods.
WHAT if we do not override hashcode. IS IT A MUST TO OVERRIDE BOTH.If it is not what is the disadvantage of overriding equals and not hashcode and vice versa.
Properly implementing hashCode is necessary for your object to be a key in hash-based containers. It is not necessary for anything else.
Here's why it is important for hash-based containers such as HashMap, HashSet, ConcurrentHashMap etc.
At a high level, a HashMap is an array, indexed by the hashCode of the key, whose entries are "chains" - lists of (key, value) pairs where all keys in a particular chain have the same hash code. For a refresher on hashtables, see Wikipedia.
Consider what happens if two keys A, B are equal, but have a different hash code - for example, a.hashCode() == 42 and b.hashCode() == 37. Suppose you write:
hashTable.put(a, "foo");
hashTable.get(b);
Since the keys are equal, you would like the result to be "foo", right?
However, get(b) will look into the chain corresponding to hash 37, while the pair (a, "foo") is located in the chain corresponding to hash 42, so the lookup will fail and you'll get null.
This is why it is important that equal objects have equal hash codes if you intend to use the object as a key in a hash-based container.
Note that if you use a non-hash based container, such as TreeMap, then you don't have to implement hashCode because the container doesn't use it. Instead, in case of TreeMap, you should implement compareTo - other types of containers may have their own requirements.
Yes it's correct when you override equals method you have to override hashcode method as well. The reason behind is that in hash base elements two objects are equal if their equals method return true and their hashcode method return same integer value. In hash base elements (hash map) when you make the equal check for two objects first their hashcode method is get called, if it return same value for both then only equals method is get called. If hashcode don't return same value for both then it simplity consider both objects as not equal. By default the hashcode method return some random value, so if you are making two objects equal for some specific condition by overriding equals method, they still won't equal because their hashcode value is different, so in order to make their hascode value equal you have to override it. Otherwise you won't be able to make this object as a key to your hash map.

Java: Map with doubleKey type, how to make the right hashCode()?

I have a MultiKey object as keys for a Map.
A Key consists of a Name (String) and an ID (int).
The following contract has to be fullfilled:
Keys have to be equal if either the names of both keys are equal or the ids of both keys.
How do I have to implement the hashCode() function so that this contract is not violated? Is it even possible?
Implementing equals is easy... i just put:
if (name.equals(other.name) || id == other.id)
return true;
But this won't work because hashMap only uses hashCode() and does not care about equals()...
Example:
Map A = [ ("tom",1)=TOMAS, ("eli",2)=ELIAS ]
A.get(new Key("tom",0)) should return TOMAS
A.get(new Key("",1)) should return TOMAS
A.get(new Key("eli",2)) should return ELIAS
...
About the only way I can see to do this would be to build a set to TreeSet to cache the hashCodes for the keys. Then use the first equals value encountered as the hashCode value for the current execution. Problems with this:
a. Can use a lot of extra memory if there are many distinct keys.
b. The hashCode values will not necessarily be consistent across multiple executions of the program.
c. If multi-threaded, synchronization will be required against the cached hashCodes.
If you do this, the hashCode could simply be generated combining name and id like you always would.
The worst case scenario: always return the same hashCode. The specs say in short: - if 2 objects are equal, they must have the same hashCode. If 2 objects are unequal, they can still have the same hashCode. A hashCode is there primarily for performance.

How does Java determine uniqueness of Hashmap key?

I want to maintain a list of objects such that each object in the list is unique.Also I want to retrieve it at one point. Objects are in thousands and I can't modify their source to add a unique id. Also hascodes are unreliable.
My approach was to utilize the key uniqueness of a map.
Say a maintain a map like :
HashMap<Object,int> uniqueObjectMap.
I will add object to map with as a key and set a random int as value. But how does java determine if the object is unique when used as a key ?
Say,
List listOne;
List listTwo;
Object o = new Object;
listOne.add(o);
listTwo.add(o);
uniqueObjectMap.put(listOne.get(0),randomInt()); // -- > line 1
uniqueObjectMap.put(listTw0.get(0),randomInt()); // --> line 2
Will line 2 give an unique key violation error since both are referring to the same object o ?
Edit
So if will unqiueObjectMap.containsKey(listTwo.get(0)) return true ? How are objects determined to be equal here ? Is a field by field comparison done ? Can I rely on this to make sure only one copy of ANY type of object is maintained in the map as key ?
Will line 2 give an unique key violation error since both are referring to the same object o ?
- No. If a key is found to be already present, then its value will be overwritten with the new one.
Next, HashMap has a separate hash() method which Applies a supplemental hash function to a given hashCode (of key objects), which defends against poor quality hash functions.
It does so by calling the Object's hashcode() function.
The default implementation is roughly equivalent to the object's unique identifier (much like a memory address); however, there are objects that are compare-by-value. If dealing with a compare-by-value object, hashcode() will be overridden to compute a number based on the values, such that two identical values yield the same hashcode() number.
As for the collection items that are hash based, the put(...) operation is fine with putting something over the original location. In short, if two objects yeild the same hashcode() and a positive equals(...) result, then operations will assume that they are for all practical purposes the same object. Thus, put may replace the old with the new, or do nothing, as the object is considered the same.
It may not store two copies in the same "place" as it makes no sense to store two copies at the same location. Thus, sets will only contain one copy, as will map keys; however, lists will possibly contain two copies, depending on how you added the second copy.
How are objects determined to be equal here ?
By using equals and Hashcode function of Object class.
Is a field by field comparison done ?
No, if you dont implement equals and hashcode, java will compare the references of your objects.
Can I rely on this to make sure only one copy of ANY type of object is maintained in the map as key ?
No.
Using a Set is a better approch than using Map because it removes duplicates by his own, but in this case it wont work either because Set determinates duplicates the same way like a Map does it with Keys.
If you will refer to same then it ll not throw an error because when HashMap get same key then it's related value will be overwrite.
If the same key is exist in HashMap then it will be overwritten.
if you want to check if the key or value is already exist or not then you can use:
containsKey() and containsValue().
ex :
hashMap.containsKey(0);
this will return true if the key named 0 is already exist otherwise false.
By getting hashcode value using hash(key.hashCode())
HashMap has an inner class Entry with attributes
final K key;
V value;
Entry<K ,V> next;
final int hash;
Hash value is used to calculate the index in the array for storing Entry object, there might be the scenario where 2 unequal object can have same equal hash value.
Entry objects are stored in linked list form, in case of collision, all entry object with same hash value are stored in same Linkedlist but equal method will test for true equality. In this way, HashMap ensure the uniqueness of keys.

Hashing function and keys

While going through Kathy Sierra's book I stumbled across this code fragment:
m.put("k1", new Dog("aiko")); // add some key/value pairs
m.put("k2", Pets.DOG);
m.put(Pets.CAT, "CAT key");
Dog d1 = new Dog("clover");
m.put(d1, "Dog key");
m.put(new Cat(), "Cat key");
Maps are used to store stuff in the keys and values format. Would someone tell me what is actually stored in key when we enter "k1" or new Cat() as a key? Are references to these objects are stored or the value of hashcode? I am totally confused with this. Please advice.
And it would be appreciated if you could point me towards further reading material.
The map is an array of N buckets.
The put() method starts by calling hashCode() on your key. From this hash code, it uses a modulo to get the index of the bucket in the map.
Then, it iterates through the entries stored in the linked list associated with the found bucket, and compares each entry key with your key, using the equals() method.
If one entry has a key equal to your key, its value is replaced by the new value. Else, a new entry is created with the new key and the new value, and stored in the linked list associated with the bucket.
Since Cat instances and String instances are never equal, a value associated with a String key will never be modified by putting a value associated with a Cat key.
It will be defined by your object.
You have to create a hashCode() and a equals() method so it can be stored in your hashtable.
As much as is reasonably practical, the hashCode method defined by class Object does return distinct integers for distinct objects. (This is typically implemented by converting the internal address of the object into an integer, but this implementation technique is not required by the JavaTM programming language.)
See the javadoc at java.lang.Object http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/Object.html#hashCode()
or you can read this for an explanation
http://www.javaworld.com/javaworld/javaqa/2002-06/01-qa-0621-hashtable.html
I hope it helps
Storing the value to HashMap depends on the hashcode() and equals() method.Please find the more reference from here.
HashMap - hashcode() Example
More information of HashMap get() retrieval of values.Here
When a HashMap is used, the keys in it are unique. This uniqueness of the keys is checked in Java from the definition of the equals() and hashCode() methods that the class of the objects under consideration provides.
This is done by comparing using the equals() method first and if it returns equal then comparing using hashCode().Also, you must be knowing that each reference pointing to an object has a bit pattern which may be different for multiple references referring to the same object.
Hence, once the equals() test passes, the object won't be inserted into the map since the map should have unique keys. So, each hashCode value for objects which are keys in the map will form different buckets for a range of hashCode values and the object will be grouped accordingly.
EDIT to provide an example:
For example, let us consider that two objects have a String attribute with values "hello" and "hlleo" and suppose the hashCode() function is programmed such that the hash code of an object is the sum of the ASCII values of the characters in the String attribute and the equals() method returns true if the values of the String attribute are equal.
So, in the above case, equals() return false as the strings are not equal but the hashCode will be same. So the two objects will be placed in the same hash code bucket.
Hope that helps.

How to ensure hashCode() is consistent with equals()?

When overriding the equals() function of java.lang.Object, the javadocs suggest 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.
The hashCode() method must return a unique integer for each object (this is easy to do when comparing objects based on memory location, simply return the unique integer address of the object)
How should a hashCode() method be overriden so that it returns a unique integer for each object based only on that object's properities?
public class People{
public String name;
public int age;
public int hashCode(){
// How to get a unique integer based on name and age?
}
}
/*******************************/
public class App{
public static void main( String args[] ){
People mike = new People();
People melissa = new People();
mike.name = "mike";
mike.age = 23;
melissa.name = "melissa";
melissa.age = 24;
System.out.println( mike.hasCode() ); // output?
System.out.println( melissa.hashCode(); // output?
}
}
It doesn't say the hashcode for an object has to be completely unique, only that the hashcode for two equal objects returns the same hashcode. It's entirely legal to have two non-equal objects return the same hashcode. However, the more unique a hashcode distribution is over a set of objects, the better performance you'll get out of HashMaps and other operations that use the hashCode.
IDEs such as IntelliJ Idea have built-in generators for equals and hashCode that generally do a pretty good job at coming up with "good enough" code for most objects (and probably better than some hand-crafted overly-clever hash functions).
For example, here's a hashCode function that Idea generates for your People class:
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + age;
return result;
}
I won't go in to the details of hashCode uniqueness as Marc has already addressed it. For your People class, you first need to decide what equality of a person means. Maybe equality is based solely on their name, maybe it's based on name and age. It will be domain specific. Let's say equality is based on name and age. Your overridden equals would look like
public boolean equals(Object obj) {
if (this==obj) return true;
if (obj==null) return false;
if (!(getClass().equals(obj.getClass())) return false;
Person other = (Person)obj;
return (name==null ? other.name==null : name.equals(other.name)) &&
age==other.age;
}
Any time you override equals you must override hashCode. Furthermore, hashCode can't use any more fields in its computation than equals did. Most of the time you must add or exclusive-or the hash code of the various fields (hashCode should be fast to compute). So a valid hashCode method might look like:
public int hashCode() {
return (name==null ? 17 : name.hashCode()) ^ age;
}
Note that the following is not valid as it uses a field that equals didn't (height). In this case two "equals" objects could have a different hash code.
public int hashCode() {
return (name==null ? 17 : name.hashCode()) ^ age ^ height;
}
Also, it's perfectly valid for two non-equals objects to have the same hash code:
public int hashCode() {
return age;
}
In this case Jane age 30 is not equal to Bob age 30, yet both their hash codes are 30. While valid this is undesirable for performance in hash-based collections.
Another question asks if there are some basic low-level things that all programmers should know, and I think hash lookups are one of those. So here goes.
A hash table (note that I'm not using an actual classname) is basically an array of linked lists. To find something in the table, you first compute the hashcode of that something, then mod it by the size of the table. This is an index into the array, and you get a linked list at that index. You then traverse the list until you find your object.
Since array retrieval is O(1), and linked list traversal is O(n), you want a hash function that creates as random a distribution as possible, so that objects will be hashed to different lists. Every object could return the value 0 as its hashcode, and a hash table would still work, but it would essentially be a long linked-list at element 0 of the array.
You also generally want the array to be large, which increases the chances that the object will be in a list of length 1. The Java HashMap, for example, increases the size of the array when the number of entries in the map is > 75% of the size of the array. There's a tradeoff here: you can have a huge array with very few entries and waste memory, or a smaller array where each element in the array is a list with > 1 entries, and waste time traversing. A perfect hash would assign each object to a unique location in the array, with no wasted space.
The term "perfect hash" is a real term, and in some cases you can create a hash function that provides a unique number for each object. This is only possible when you know the set of all possible values. In the general case, you can't achieve this, and there will be some values that return the same hashcode. This is simple mathematics: if you have a string that's more than 4 bytes long, you can't create a unique 4-byte hashcode.
One interesting tidbit: hash arrays are generally sized based on prime numbers, to give the best chance for random allocation when you mod the results, regardless of how random the hashcodes really are.
Edit based on comments:
1) A linked list is not the only way to represent the objects that have the same hashcode, although that is the method used by the JDK 1.5 HashMap. Although less memory-efficient than a simple array, it does arguably create less churn when rehashing (because the entries can be unlinked from one bucket and relinked to another).
2) As of JDK 1.4, the HashMap class uses an array sized as a power of 2; prior to that it used 2^N+1, which I believe is prime for N <= 32. This does not speed up array indexing per se, but does allow the array index to be computed with a bitwise AND rather than a division, as noted by Neil Coffey. Personally, I'd question this as premature optimization, but given the list of authors on HashMap, I'll assume there is some real benefit.
In general the hash code cannot be unique, as there are more values than possible hash codes (integers).
A good hash code distributes the values well over the integers.
A bad one could always give the same value and still be logically correct, it would just lead to unacceptably inefficient hash tables.
Equal values must have the same hash value for hash tables to work correctly.
Otherwise you could add a key to a hash table, then try to look it up via an equal value with a different hash code and not find it.
Or you could put an equal value with a different hash code and have two equal values at different places in the hash table.
In practice you usually select a subset of the fields to be taken into account in both the hashCode() and the equals() method.
I think you misunderstood it. The hashcode does not have to be unique to each object (after all, it is a hash code) though you obviously don't want it to be identical for all objects. You do, however, need it to be identical to all objects that are equal, otherwise things like the standard collections would not work (e.g., you'd look up something in the hash set but would not find it).
For straightforward attributes, some IDEs have hashcode function builders.
If you don't use IDEs, consider using Apahce Commons and the class HashCodeBuilder
The only contractual obligation for hashCode is for it to be consistent. The fields used in creating the hashCode value must be the same or a subset of the fields used in the equals method. This means returning 0 for all values is valid, although not efficient.
One can check if hashCode is consistent via a unit test. I written an abstract class called EqualityTestCase, which does a handful of hashCode checks. One simply has to extend the test case and implement two or three factory methods. The test does a very crude job of testing if the hashCode is efficient.
This is what documentation tells us as for hash code method
# javadoc
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.
There is a notion of business key, which determines uniqueness of separate instances of the same type. Each specific type (class) that models a separate entity from the target domain (e.g. vehicle in a fleet system) should have a business key, which is represented by one or more class fields. Methods equals() and hasCode() should both be implemented using the fields, which make up a business key. This ensures that both methods consistent with each other.

Categories

Resources