9 Replies Latest reply on Feb 10, 2011 11:03 AM by EJP

# HashMap.hashCode() for HashMap with keys equaling their values

Hi

I've found something strange with Hashmaps:

in the following code:

HashMap<Integer,Integer> m1 = new HashMap<Integer,Integer>();
HashMap<Integer,Integer> m2 = new HashMap<Integer,Integer>();
m1.put(1,1);
m1.put(2,2);

m2.put(2,2);
m2.put(1,1);
m2.put(5,5);

System.out.println(m1.equals(m2));
System.out.println(m1.hashCode());
System.out.println(m2.hashCode());

0
0
false

It seems that when a HashMap receives key/value pairs where key = value its hashCode becomes 0!
I'm pretty sure I haven't just stumbled on a bug in the Collections framework so could someone please explain to me why this occurs?

ps: If your wondering why on earth someone would want to make such a Hashmap, I've found it useful in the following situation:

class MyCount {
int count;
String name;
int age;

MyCount(String name, int age) {
this.name = name;
this.age = age;
count = 0;
}

count += c;
}

public int hashCode() {
return 31 * age + name.hashCode();
}
}

class MyCountClusterer {
Collection<MyCount> cluster(MyCount[] counts) {
HashMap<MyCount, MyCount> countMap = new HashMap<MyCount, MyCount>();
for (MyCount c : counts) {
MyCount mapC = countMap.get(c);
if (mapC == null) {
mapC = new MyCount(c.name, c.age);
countMap.put(c, c);
}
}
return countMap.values();
}
}
• ###### 1. Re: HashMap.hashCode() for HashMap with keys equaling their values
I don't understand your problem! How do you think the hashCode() of a HashMap should be related to the content of the HashMap ?
• ###### 2. Re: HashMap.hashCode() for HashMap with keys equaling their values
That's an unfortunate result of the way HashEntry.hashCode() is defined.

In your case I'd remove count from the MyCount class and replace the value with an AtomicInteger.
• ###### 3. Re: HashMap.hashCode() for HashMap with keys equaling their values
the hashCode of the HashMap has to reflect the HashMaps content in order to properly differentiate between two HashMap objects.

for example:

HashMap<Integer, Integer> m1 = new HashMap<Integer, Integer>();
HashMap<Integer, Integer> m2 = new HashMap<Integer, Integer>();
m1.put(1, 5);
m1.put(2, 16);

m2.put(1, 34);
m2.put(2, 21);
m2.put(3, 7);

System.out.println(m1.equals(m2));
System.out.println(m1.hashCode());
System.out.println(m2.hashCode());

Output:
false
22
62
• ###### 4. Re: HashMap.hashCode() for HashMap with keys equaling their values
Thanks for the sanity check

Although my MyCount class was just an example in more complex examples an AtomicInteger wouldn't be sufficient
• ###### 5. Re: HashMap.hashCode() for HashMap with keys equaling their values
user7725982 wrote:
the hashCode of the HashMap has to reflect the HashMaps content in order to properly differentiate between two HashMap objects.
Not true. Only the equals() method is needed for this. Whether or not the hashCode() has to be constant depends on the usage. If you are adding it to a HashSet or using it as the key to a HashMap then it needs to be immutable but you can use the same hashCode for all objects. The lookup then degenerates to a linear search. Any object used as a key to a HashMap should be immutable as far as hashCode() and equals() are concerned.
• ###### 6. Re: HashMap.hashCode() for HashMap with keys equaling their values
sabre150 wrote:
Not true. Only the equals() method is needed for this.
Your right, hashCode() is needed for insertion in HashSets and HashMaps not for the equals() method
sabre150 wrote:
If you are adding it to a HashSet or using it as the key to a HashMap then it needs to be immutable but you can use the same >hashCode for all objects. The lookup then degenerates to a linear search
Not true, If two objects with the same hashCode() are consecutively added to a HashSet then the second Object replaces the first one. Similarly for HashMap keys.
• ###### 7. Re: HashMap.hashCode() for HashMap with keys equaling their values
user7725982 wrote:
If you are adding it to a HashSet or using it as the key to a HashMap then it needs to be immutable but you can use the same >hashCode for all objects. The lookup then degenerates to a linear search
Not true, If two objects with the same hashCode() are consecutively added to a HashSet then the second Object replaces the first one. Similarly for HashMap keys.
Not true.
``````      String s1 = "ABCDEa123abc";
String s2 = "ABCDFB123abc";
int hash1 = s1.hashCode();
int hash2 = s2.hashCode();
System.out.println(hash1 + " " + hash2);

Set<String> set = new HashSet<String>();