implementing hashcode and equals

Is there anything more than performance reasons to always implement hashCode when you implement equals? If I understand correctly, when you put items in a hashtable it chooses the bucket by the hashcode and checks there is no equal item with the equals method. So it should still work if you never implement the hashcode method. But is there any other reason to implement hashCode than performance? Or have I just understood this completely wrong?

[468 byte] By [teka] at [2008-3-7]
# 1

Hashcode is used when the class which implements the hashcode method is used as an element of a datastructure.

Eg: if the class were to be contained in a hashtable.

Equals method is particularly used in EJB environment. The container uses the equals method to check if two bean instances refer to the same data, before persistence.

jaya-shree at 2007-7-1 > top of java,Administration Tools,Sun Connection...
# 2

> Is there anything more than performance reasons to

> always implement hashCode when you implement equals?

Yes. Read the API docs for equals and hashCode. In particular, notice that to obey the contracts, any two objects for which equals returns true, must have the same hashCode.

> If I understand correctly, when you put items in a

> hashtable it chooses the bucket by the hashcode and

> checks there is no equal item with the equals method.

If you use two equal keys in the hashtable, the second should overwrite the first. If they have different hashcodes, this will not happen.

> So it should still work if you never implement the

> hashcode method. But is there any other reason to

> implement hashCode than performance? Or have I just

> understood this completely wrong?

Consider the following code (I have implemented equals, but not implemented hashCode). Run it, then uncomment the hashCode method and run it again:

import java.util.HashSet;

import java.util.Set;

public final class MyObject {

private int i;

MyObject(int i) {

this.i = i;

}

public final boolean equals(Object obj) {

if (obj == this) {

return true;

}

if (!(obj instanceof MyObject)) {

return false;

}

MyObject that = (MyObject)obj;

return this.i == that.i;

}

//public int hashCode() {

//return i;

//}

public static void main(String[] args) {

MyObject obj1 = new MyObject(1);

MyObject obj2 = new MyObject(1);

System.out.println("obj1.equals(obj2): "+obj1.equals(obj2));

System.out.println("obj1.hashCode(): "+obj1.hashCode());

System.out.println("obj2.hashCode(): "+obj2.hashCode());

Set set = new HashSet();

set.add(obj1);

System.out.println("set.size(): "+set.size());

System.out.println("set.contains(obj2): "+set.contains(obj2));

set.add(obj2);

System.out.println("set.size(): "+set.size());

}

}

mattbunch at 2007-7-1 > top of java,Administration Tools,Sun Connection...
# 3

Everything you say is true. And your example shows that point well. However, what if I just implement a hashCode that always returns 0? How will this work then? And does it have any differences than performance?

Here is an example

[code]

import junit.framework.*;

import java.util.*;

public class EqualsTest extends TestCase

{

public void testHashCode()

{

Map hashTable = new Hashtable();

hashTable.put( new TestItem( 0 ), "0" );

hashTable.put( new TestItem( 1 ), "1" );

assertEquals( 2, hashTable.size() );

Set hashSet = new HashSet();

hashSet.add( new TestItem( 0 ));

hashSet.add( new TestItem( 1 ) );

assertEquals( 2, hashSet.size() );

}

private class TestItem

{

private final int i;

public TestItem( int i )

{

this.i = i;

}

public boolean equals( Object o )

{

final TestItem testItem = ( TestItem ) o;

return i == testItem.i;

}

public int hashCode()

{

return 0;

}

}

}

[/code}

teka at 2007-7-1 > top of java,Administration Tools,Sun Connection...
# 4

> what if I just implement a

> hashCode that always returns 0?

That would be a perfectly valid hashCode method. However, every object will hash to the same bucket in a hashtable. So you effectively end up with a list instead of a map whenever your objects are used in a hashtable. This completely defeats the purpose of hashtables, and for a large hashtable you might find your apps grind to a halt.

mattbunch at 2007-7-1 > top of java,Administration Tools,Sun Connection...
# 5
Yes that is what I was thinking. Thank you for your answers.
teka at 2007-7-1 > top of java,Administration Tools,Sun Connection...