开发者

Java: overriding equals method doesn't do the trick when looking for a key of hashtable?

I have a hashtable looking like this:

Hashtable<Mapping, Integer> mappingCount = new Hashtable<Mapping, Integer>();

I want to use this code:

if (mappingCount.get(currentMapping) != null)
    mappingCount.put(currentMapping, mappingCount.get(currentMapping) + 1);
else
    mappingCount.put(currentMapping, 1);

In order to be able to get the value from the hashtable, for the class Mapping I did the following:

@Override
public boolean equals(Object obj) {
    return ((Mapping)obj).mappingXML.equals(this.mappingXML);
}

However, this doesn't do the trick since mappingCount.get(currentMapping) always results in null. To be sure that something's not wrong, I d开发者_如何学运维id the following:

if (aaa.contains(currentMapping.getMappingXML()))
    System.out.println("found it!");
else
    aaa.add(currentMapping.getMappingXML());

where aaa is List<String> aaa = new ArrayList<String>(). Of course, found it is printed many times. What am I doing wrong?


You also need to override the hashCode() method.

From the JavaDocs:

To successfully store and retrieve objects from a hashtable, the objects used as keys must implement the hashCode method and the equals method.

The reason for this is that Hashtable uses hashCode as a preliminary test to see if two objects are equals. If the hashCode matches, then it uses equals to check for collissions.

The default implementation of hashCode() returns the memory address of the object, and for two objects that are equal, their hashcodes must also be equal.

Also look at the general contract for hashCode().


All of the recommendations to override equals and hash code correctly are spot on; Joshua Bloch tells you how to do it properly.

But an equally important requirement is that keys in maps must be immutable. If your class can change its values, then the equals and hash code can change after you add it to the map; disaster ensues.


Whenever you override equals, you must override hashCode as well.


You need to override hashCode as well.

From the Object#hashCode doc:

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 JavaTM programming language.)


You have to implement hashcode() as well!

Example:

public class Employee{
    int        employeeId;
    String     name;
    Department dept;

    // other methods would be in here 

    @Override
    public int hashCode() {
        int hash = 1;
        hash = hash * 17 + employeeId;
        hash = hash * 31 + name.hashCode();
        hash = hash * 13 + (dept == null ? 0 : dept.hashCode());
        return hash;
    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜