Solved

Implementation of the hash code method

Posted on 2002-07-10
13
292 Views
Last Modified: 2013-11-23
Hello sir/madam,

  How do i implement the hashCode and equals() method on the class?Kindly elaborate...
  I am having  a problem in the implementation Class of the ManagedConnectionFactory of the J2EE connector architecture specifications..
Regards
Anuradha
0
Comment
Question by:anuchoudhry
13 Comments
 
LVL 86

Expert Comment

by:CEHJ
Comment Utility
The hashCode() method can be implemented quite simply by:

return super.hashCode();

As far as the equals() method is concerned, sincce I'm not familiar with this interface, I can't really help. But generally, what you need to do is decide what fields are important in the basic functionality. It is these fields that will distinguish one interface from another. You should compare these individually and make equals() method reflect this. The same fields, of course, would be important in supplying a toString() method, which you should also implement probably.
0
 
LVL 9

Expert Comment

by:doronb
Comment Utility
0
 
LVL 9

Accepted Solution

by:
doronb earned 20 total points
Comment Utility
Hi,


The hashCode() method must never be implemented by:

return super.hashCode();

because then you are simply calling hashCode on the class that your class inherits from; invocation of the inherited super.hashCode method would happen normally since the method is inherited so strictly invoking the

super method is not going to change anything and supply a better hashCode than the super class would have.

The 2nd thing to remember is that most object inherit their hashCode implementation from the java.lang.Object which simply returns the memory location of the java object in question. This simple implementation is

good enough if the state which the object is in when you're asking for the hashCode should NEVER determine the hashCode value itself!!!

Most objects that contain data relevant to the hashCode (for example, objects that are keys or ID's) should not allow the data to change once the hashCode has been calculated and used (to store the object as a key in

a HashMap for instance). Changing the data for the object would render the hashCode value incompatible with the data.

In some cases, objects can re-calculate their hashCode based on their current data but this scenario is too complicated to explain right now, so lets stick with objects that calculate their hashCode only once and do not

allow their data to change once the hashCode has been calculated.

The code in my next post shows how an object can hold data used when calculating the hashCode. Once the hashCode has been calculated, the data members can never be changed!! Since the hashCode is determined by the data members, the equals method is also added to verify that two instances are equal if they contain the same data in their data members.

continued --->
0
 
LVL 9

Expert Comment

by:doronb
Comment Utility
The code:

package <your-package>;

import java.io.Serializable;

public class RemoteClientId implements Serializable {
     private String clientIpAddress;
     private long timeStampKey;
     private transient int hashCodeValue;

     public RemoteClientId() {
          clientIpAddress = null;
          timeStampKey = 0;
          hashCodeValue = 0;
     }

     public RemoteClientId(String ip, long timeStamp) {
          setClientIpAddress(ip);
          setTimeStampKey(timeStamp);
          hashCodeValue = calcHashCode();
     }

     private int calcHashCode() {
          int result = hashCodeValue;
          try {
               byte[] ba1 = clientIpAddress.getBytes();
               byte[] ba2 = Long.toBinaryString(timeStampKey).getBytes();
               int i;
               int k = 1;
               for (i = 0; i < ba1.length; i++) {
                    result += (int)ba1[i] * k;
                    k++;
               }
               for (i = 0; i < ba2.length; i++) {
                    result += (int)ba2[i] * k;
                    k++;
               }
          } catch (NullPointerException ex) {
               if (clientIpAddress != null) {
                    // This address is invalid so create an illegal hashCode..
                    result = -1;
               }
          } catch (Exception ex) {
               ex.printStackTrace();
          }
          return result;
     }

     public int hashCode() {
          if (hashCodeValue == 0) {
               hashCodeValue = calcHashCode();
          }
          return hashCodeValue;
     }

     public boolean equals(Object that) {
          if (!(that instanceof RemoteClientId)) {
               RemoteClientId rci = (RemoteClientId)that;
               return (rci.timeStampKey != timeStampKey) ? false : ((clientIpAddress == null) ? (rci.clientIpAddress == null) : clientIpAddress.equals(rci.clientIpAddress));
          }
          return false;
     }

     public void setClientIpAddress(String ip) {
          if (hashCodeValue == 0) {
               clientIpAddress = ip;
          }
     }

     public void setTimeStampKey(long timeStamp) {
          if (hashCodeValue == 0) {
               timeStampKey = timeStamp;
          }
     }

     public String getClientIpAddress() {
          return clientIpAddress;
     }

     public long getTimeStampKey() {
          return timeStampKey;
     }
}


Hope this helps,
Doron
0
 
LVL 3

Expert Comment

by:yasser_helmy
Comment Utility
I think doron gave some very valuable info. I want to add some thing. If the equals() method returns true for any two objects, the hashCode() method of the two objects would logically return equal values.
The equals() method compares should compare the fields of the two objects and returns true if and only if the fields are equal.
0
 
LVL 86

Expert Comment

by:CEHJ
Comment Utility
>>If the equals() method returns true for any two objects, the hashCode() method of the two objects would logically return equal values.

That should only be the case if (o1 == o2) == true

otherwise you would be contradicting doronb's observation

>>The 2nd thing to remember is that most object inherit their hashCode implementation from the java.lang.Object which simply returns the memory location of the java object in question

since two different [but equal()] objects can't have the same reference

>>The equals() method compares should compare the fields of the two objects and returns true if and only if the fields are equal.

Not necessarily *all* the fields. There may be some that are unequal that are of no importance at all to the client.
0
Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

 
LVL 9

Expert Comment

by:doronb
Comment Utility
Hi again,


A great source for discussion and examples about equals and hashCode is the book "EFFECTIVE JAVA Programming Language Guide by Joshua Bloch" displayed at http://java.sun.com/docs/books/effective/

Chapter 3, Item #8 talks EXACTLY about overriding the hashCode and equals methods.


Good luck,
Doron
0
 
LVL 9

Expert Comment

by:doronb
Comment Utility
One concept that you must INSIST on is that if you're overriding hashCode, you should override equals and vice versa, NOT doing so is at the programmer's responsibility >;)
0
 
LVL 86

Expert Comment

by:CEHJ
Comment Utility
>>
The hashCode() method must never be implemented by:

return super.hashCode();
>>

This is a little harsh doronb! Especially as the book you recommended by Joshua Bloch has the following code as an example for Chapter 5:

public final int hashCode() {
        return super.hashCode();
    }

However I agree that:

>>
super method is not going to change anything and supply a better hashCode than the super class would have.
>>

So you may as well allow the superinterface's hashCode() method to be called.

Since this hash got a bit theoretical in parts, perhaps : anuchoudhry would like clarification?
0
 
LVL 9

Expert Comment

by:doronb
Comment Utility
Hi CEHJ,


Please note the "final" keyword in your example. I will explain its presence with an example:

class A {
  public int hashCode() {
    // Do some complex stuff, return value..
  }
}

class B extends A {
  public final int hashCode() {
    // Stop anyone from overriding
    // the hashCode method if
    // inherited from class B!
    return super.hashCode();
  }
}

There is one more case where I would use super.hashCode and that is if my hashCode relies on my super-class hashCode. I can't imagine right now some problem that would make me do that, but I'm sure one can be found. :)

Doron
0
 
LVL 86

Expert Comment

by:CEHJ
Comment Utility
Yes, I see. Of course! Thanks doronb.
0
 
LVL 7

Expert Comment

by:Igor Bazarny
Comment Utility
Hi,

> This is a little harsh doronb! Especially as the book you recommended by Joshua Bloch has the following code as an example for Chapter 5:
Note that Chapter 5 is titled 'Substitutes for C Constructs'. I guess you took your sample from the Item 21: Replace enum constructs with classes. In that spacific context, Object equals() and hashCode() behavior is correct, because each 'enum' value has it's own identity, so == comparison of such objects is OK (Object.equals() implementation is almost equivalent to pointer equality, it only doesn't work for null).

anuchoudhry,
Note that you need equals() and hashCode() implementation only if you need to compare your objects or use them as HashMap keys (or store in HashSet, it's almost the same). java.lang.Object provides default implementation of equals() which simply compares references, and hashCode() returns some kind of address value (you can't turn it into reference though).

Read Object.eqauls() and Object.hashCode() for the rules:

The equals method implements an equivalence relation:

equals() rules:

- It is reflexive: for any reference value x, x.equals(x) should return true.
- It is symmetric: for any reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true.
- It is transitive: for any reference values x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true.
- It is consistent: for any reference values x and y, multiple invocations of x.equals(y) consistently return true or consistently return false, provided no information used in equals comparisons on the object is modified.
- For any non-null reference value x, x.equals(null) should return false.

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.

Regards,
Igor Bazarny,
Brainbench MVP for Java 1
0
 
LVL 35

Expert Comment

by:girionis
Comment Utility
No comment has been added lately, so it's time to clean up this TA.

I will leave a recommendation in the Cleanup topic area that this question is:

- points to doronb

Please leave any comments here within the
next seven days.

PLEASE DO NOT ACCEPT THIS COMMENT AS AN ANSWER !

girionis
Cleanup Volunteer
0

Featured Post

Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

Join & Write a Comment

After being asked a question last year, I went into one of my moods where I did some research and code just for the fun and learning of it all.  Subsequently, from this journey, I put together this article on "Range Searching Using Visual Basic.NET …
Java contains several comparison operators (e.g., <, <=, >, >=, ==, !=) that allow you to compare primitive values. However, these operators cannot be used to compare the contents of objects. Interface Comparable is used to allow objects of a cl…
Viewers learn how to read error messages and identify possible mistakes that could cause hours of frustration. Coding is as much about debugging your code as it is about writing it. Define Error Message: Line Numbers: Type of Error: Break Down…
This tutorial covers a step-by-step guide to install VisualVM launcher in eclipse.

772 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now