Wednesday, 3 September 2014

Equals and Hashcode method of Object Class

equals()

equals() is used in most collections to determine if a collection contains a given element. For instance:
List list = new ArrayList();
list.add("123");

boolean contains123 = list.contains("123");
The ArrayList iterates all its elements and execute "123".equals(element) to determine if the element is equal to the parameter object "123". It is the String.equals() implementation that determines if two strings are equal.
The equals() method is also used when removing elements. For instance:
List list = new ArrayList();
list.add("123");

boolean removed = list.remove("123");
The ArrayList again iterates all its elements and execute "123".equals(element) to determine if the element is equal to the parameter object "123". The first element it finds that is equal to the given parameter "123" is removed.
As you can see, a proper implementation of .equals() is essential for your own classes to work well with the Java Collection classes. So how do you implement equals() "properly"?
So, when are two objects equal? That depends on your application, the classes, and what you are trying to do. For instance, let's say you are loading and processing Employee objects stored in a database. Here is a simple example of such an Employee class:
public class Employee {
    protected long   employeeId;
    protected String firstName;
    protected String lastName;
}
You could decide that two Employee objects are equal to each other if just their employeeId's are equal. Or, you could decide that all fields must be equal - both employeeIdfirstName and lastName. Here are two example implementation of equals() matching these criterias:
public class Employee {
  ...
  public boolean equals(Object o){
    if(o == null)                return false;
    if(!(o instanceof) Employee) return false;

    Employee other = (Employee) o;
    return this.employeeId == other.employeeId;
  }
}
public class Employee {
  ...
  public boolean equals(Object o){
    if(o == null)                return false;
    if(!(o instanceof) Employee) return false;

    Employee other = (Employee) o;
    if(this.employeeId != other.employeeId)      return false;
    if(! this.firstName.equals(other.firstName)) return false;
    if(! this.lastName.equals(other.lastName))   return false;

    return true;
  }
}
Which of these two implementations is "proper" depends on what you need to do. Sometimes you need to lookup anEmployee object from a cache. In that case perhaps all you need is for the employeeId to be equal. In other cases you may need more than that - for instance to determine if a copy of an Employee object has changed from the original.

hashCode()

The hashCode() method of objects is used when you insert them into a HashTableHashMap or HashSet. If you do not know the theory of how a hashtable works internally, you can read about hastables on Wikipedia.org.
When inserting an object into a hastable you use a key. The hash code of this key is calculated, and used to determine where to store the object internally. When you need to lookup an object in a hashtable you also use a key. The hash code of this key is calculated and used to determine where to search for the object.
The hash code only points to a certain "area" (or list, bucket etc) internally. Since different key objects could potentially have the same hash code, the hash code itself is no guarantee that the right key is found. The hashtable then iterates this area (all keys with the same hash code) and uses the key's equals() method to find the right key. Once the right key is found, the object stored for that key is returned.
So, as you can see, a combination of the hashCode() and equals() methods are used when storing and when looking up objects in a hashtable.
Here are two rules that are good to know about implementing the hashCode() method in your own classes, if the hashtables in the Java Collections API are to work correctly:
  1. If object1 and object2 are equal according to their equals() method, they must also have the same hash code.
  2. If object1 and object2 have the same hash code, they do NOT have to be equal too.
In shorter words:
  1. If equal, then same hash codes too.
  2. Same hash codes no guarantee of being equal.
Here are two example implementation of the hashCode() method matching the equals() methods shown earlier:
public class Employee {
  protected long   employeeId;
  protected String firstName;
  protected String lastName;

  public int hashCode(){
    return (int) this.employeeId;
  }
}
public class Employee {
    protected long   employeeId;
    protected String firstName;
    protected String lastName;

  public int hashCode(Object o){
    return (int)this.employeeId *
                firstName.hashCode() *
                lastName.hashCode();
  }
}
Notice, that if two Employee objects are equal, they will also have the same hash code. But, as is especially easy to see in the first example, two Employee objects can be not equal, and still have the same hash code.
In both examples the hash code is the employeeId is rounded down to an int. That means that many employee id's could result in the same hash code, but these Employee objects would still not be equal, since they don't have the same employee id.

Wait and Notify method Example

1. Some background knowledge
  1. synchronized keyword is used for exclusive accessing.
  2. To make a method synchronized, simply add the synchronized keyword to its declaration. Then no two invocations of synchronized methods on the same object can interleave with each other.
  3. Synchronized statements must specify the object that provides the intrinsic lock. When synchronized(this) is used, you have to avoid to synchronizing invocations of other objects' methods.
  4. wait() tells the calling thread to give up the monitor and go to sleep until some other thread enters the same monitor and calls notify( ).
  5. notify() wakes up the first thread that called wait() on the same object.

Example: implementing a thread pool

Let's look at a common example of when we'd want to do this. Imagine that we want to implement a connection pool: a list of Connection objects (encapsulating a connection to a database) of which we want to create a fixed number and share amongst various threads. As mentioned above, in Java 5 onwards, this wouldn't commonly be implemented by the application programmer using the wait/notify mechanism, since better-performing and higher level classes are available. But pre-Java 5, it was a common use for wait/notify.
The thread pooling problem is that we want to implement a call that does the following:
  • allows any thread take a connection from the pool, if one is available;
  • else wait for one to become available.
Similarly, we want a call that allows the thread to return its connection to the pool and:
  • when a connection is returned to the pool, we want to 'hand' that connection to any waiting thread.
First, we create a ConnectionPool class and assume that it has a List of Connection objects. For the sake of argument, we'll just assume that all available connections are created when the ConnectionPool is constructed. (In reality, we'd probably want to create them on the fly, up to some maximum number.) We'll omit the part ofcreateConnections method that actually creates the connections: the only interesting feature for our purposes is that we create a fixed number of connections and add them to an unsynchronized list: for reasons we'll see in a minute, we'll always synchronize explicitly on the list when accessing it.
public class ConnectionPool {
  private List<Connection> connections = createConnections();

  private List<Connection> createConnections() {
    List<Connection> conns = new ArrayList<Connection>(5);
    for (int i = 0; i < 5; i++) {
      ... add a Connection to conns
    }
    return conns;
  }
}
Now we implement our getConnection() method. If no connection is currently available (i.e. connections is empty), then we need to wait until one becomes available. Then we return the first available connection.
public Connection getConnection() throws InterruptedException {
  synchronized (connections) {
    while (connections.isEmpty()) {
      connections.wait();
    }
    return connections.remove(0);
  }
}
Note first of all that we synchronize on the connection list. We then check if the list is empty. If, and while, it is, we "wait" on the list. In order to wait on an object, wemust be synchronized on that object. But our thread will automatically release the lock temporarily while waiting. Calling wait() means that our thread will be suspended until it is "notified". Our thread will be "notified", and thus woken up, when another thread calls notify() on the object that we're waiting on (in this case, the connection list). When our thread wakes up, it automatically regains the lock. We can now check again that the list is not empty, and if it isn't, safely take out the first connection. This checking and removing will be atomic because we have the lock on the list. (If you're unsure what this means, see the section on the synchronizedkeyword in Java.)
Now, let's look at the other side of things: the method that a thread calls to return a connection to the pool:
public void returnConnection(Connection conn) {
  synchronized (connections) {
    connections.add(conn);
    connections.notify();
  }
}
Again with a synchronized lock on the list, we add the given connection to the list. Then, while still synchronized on it, we call notify() on the connection. Callingnotify() means: "if there is at least one thread waiting on this object, please wake up one of those threads". In cases such as this, waking up a single random thread is the functionality we want: we've only added one connection to the list, so there's no point waking up more than one waiting thread. Note that we have no control over whichwaiting thread is woken up. In particular, we can't say "wake up the one that's been waiting longest". (Nor will most JVMs or OSs use such a policy: ensuring this kind of "fairness" turns out to decrease throughput considerably.)
Note that although notify() wakes up one of the waiting threads, the first thing that that thread needs to do is re-acquire the lock that our thread is currently holding. Soafter calling notify(), we should exit the synchronized block as quickly as possible. If we do something like this:
public void returnConnection(Connection conn) {
  synchronized (connections) {
    connections.add(conn);
    connections.notify();
    // bad: woken thread can't start until we
    // come out of synchronized block!
    updateStatistics(conn);
  }
}
then the woken thread won't be able to proceed until our call to updateStatistics() returns.
A couple of small points about this wait-notify pattern are worth clarifying:
  • The waiting thread can be interrupted (either for some spurious OS/hardware reason or, more likely, because interrupt() is called on the thread from within Java). Thus,wait() can throw InterruptedException. Unless you're in code that's dealing with the "outer logic" of a thread's function, the most appropriate thing is usually just to throw the exception up.
  • When a thread is 'awoken' from wait(), it can't tell why it's being woken. In particular, it isn't necessarily because it has been notified! (The OS could just spuriously wake it up for some reason.) So we have to check the size of the list again before pulling out a connection.
  • It's crucial that we don't wait if the list isn't empty. If we did, we would essentially sit waiting for a notify that wasn't about to come. (This is actually quite a common programming error in this type of code, because when you're writing it, your mind is saying "I need to wait until there's something in the list".)

Source: http://www.javamex.com/tutorials/wait_notify_how_to.shtml