Thursday, May 15, 2014

Collection API


We have read all about Collection API in various websites, books and papers.  Whenever I need to brush up my Collection API knowledge, I refer my old reference note book, in which I have a pictorial representation of the Collection API which helps me brushing up easily.  So I thought why not share it with all of you and help you brush/learn Collection API in fast mode.  So here it is, the pictorial representation of Collection API.  





Let me know about your thoughts or any thing about this picture.

Sunday, January 15, 2012

Overriding hashCode()


In the earlier post I have written about overriding equals().  A major contract of overriding equals() is, when you override equals() you have to override hashCode().  It is like they both complete each other.  It is of no using having one and not the other.  This may lead to inappropriate behaviour of the code.  The contract says:
1.      During the execution of an application the hashCode() should return consistent value no matter how many times it is called.  The integer may not remain same from one execution to another.
2.      If two objects are equal according to equals() then their hashCode() should also be same.
3.      It is not required that two different objects which are not equal according to equals(), should return different values.  Though returning different result may lead to better performance of hash tables.
So the second important point here is equal object must have equal hash codes.  Let us take an example which overrides equals() but no hashCode():
public final class PhoneNumber {
    private final int areaCode;
    private final int prefix;
    private final int lineNumber;

    public PhoneNumber(int areaCode, int prefix, int lineNumber) {
        super();
        this.areaCode = areaCode;
        this.prefix = prefix;
        this.lineNumber = lineNumber;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == this) {
            return true;
        }
        if (!(obj instanceof PhoneNumber)) {
            return false;
        }
        PhoneNumber pn = (PhoneNumber) obj;
        return pn.areaCode == this.areaCode && pn.prefix == this.prefix && pn.lineNumber == this.lineNumber;
    }
}
Now if the calling application is something like this:
Map<PhoneNumber, String> m = new HashMap<PhoneNumber, String>();
m.put(new PhoneNumber(100, 200, 300), "Radha");
m.get(new PhoneNumber(100, 200, 300));
As you can see there are 2 objects here.  1st one is creating the object in put() and the second is getting the created object.  Functionally the get() should be able to get the object, but it won’t.  It will return null.  The reason to this is we have not overridden hashCode().  What happens here is when we are calling put() the hash code is calculated and put in some bucket.  Now when get() is called it will return a different hash code which may be in different bucket.  So as the hash codes are not matching, it won’t further go ahead and match equals() and will return null.
In order to fix this let us add a hashCode() to this class.
@Override
public int hashCode() {
    return 42;
}
As you can see we are returning a constant value, which is not a good practice, but this will solve the issue as the hash code will always be same.
*Note: Please avoid returning constant.  It is just an example to show how it works
Let us discuss on the best recipe for writing a hashCode():
1.     Have a constant non zero value.  It can be anything, for e.g. 17.  Store it as result.
2.     For each field f of your object(which are used in equals()) do the following:
a. Compute an int hash code c for the field:
i. If the field is boolean, compute (f ? 1 : 0)
ii. If the field is byte, char, short or int compute (int)f
iii.   If the field is long compute (int)(f ^ (f >>>32))
iv. If the field is float compute Float.floatToIntBits(f)
v. If the field is double compute Double.doubleToLongBits(f)
vi. If the field is an object reference and this class equals()compares field by recursively invoking equals() then recursively call the hashCode() on the field by above method.  If a more complex comparison is needed, compute a canonical representation for this field and call hash code on the canonical representation.  If the value of the field is null return 0(you can return any other constant, 0 is tradition)
vii. If the field is an array, then invoke recursively all the elements applying the above rules.
b. Combine the hash code c computed in step 2.a into result as,
Result = 31* result + c
Here 31 is used because it is an odd prime.  If 2 might have been chosen then the information might have been lost because 2 is equivalent to shifting.  So it is better to choose an odd prime.
3.   Return result
So let’s have an example with this recipe:
@Override
    public int hashCode() {
        int result = 17;
        result = 31 * result + areaCode;
        result = 31 * result + prefix;
        result = 31 * result + lineNumber;
        return result;
}
This will give desired result for the PhoneNumber class. 
We can also write a hash code with lazily initialize variable if required.  That means the hash code is created and stored when the first time the object is created.  Let us see an example:
private volatile int hashCode;

    @Override
    public int hashCode() {
        int result = hashCode;
        if (result == 0) {
            result = 17;
            result = 31 * result + areaCode;
            result = 31 * result + prefix;
            result = 31 * result + lineNumber;
            hashCode = result;
        }
        return result;
    }
So this was how to override hashCode().  A cautionary item here is, do not exclude significant parts of an object from the hash code to improve performance, because although this may result in running the hash function faster but it may degrade hash table’s performance. 

*Note: You can alternatively use HashCodeBuilder from org.apache.commons.lang.builder.HashCodeBuilder. On how to use it see http://commons.apache.org/lang/api-2.5/org/apache/commons/lang/builder/HashCodeBuilder.html
{Courtesy: Effective Java - Joshua Bloch} 




Friday, January 13, 2012

Overriding equals()


Maximum of us know how to override equals() and what is the use of it.  It’s easy, but the most important part where we fail is to understand when to override. We tend to confuse whether to override an equals() or not.  It’s better to avoid equals() whenever possible.  But how come we would know that ‘whenever’. Let me list out the ‘whenever’ conditions where we should avoid overriding equals().
·        When you know that each instance of the class is unique.  For e.g. Thread, each instance has to be unique as it represents active entity.  So equals() implemented in Object class is perfect for it.
·        You are not sure whether the objects should be logical equal.  For e.g. java.util.Random could have overridden equals(), but the designers must have not be sure that the client(the end programmer) would need to know that the produced random numbers from two different instances of Random are same or not.
·        Superclass has already overridden equals() and it fits the requirement with the subclass.  For e.g. Set overrides equals() and the same implementation is used for its subclasses like HashSet. 
·        It is a private class or a package-private class and it is sure that the equals() will never be called.  Though we can override the equals() here incase accidently equals get called.  In that case we can just throw a AssertionError() in the body of equals().
Hopefully by now it is clear as to when not to override equals().
Let us discuss on how to override equals(), rather we would discuss what are the points which should be considered while overriding equals().
·        Reflexive:  Mathematically it means, for any non-null reference value x, x.equals(x) must return true.  It’s hard to violate this rule.
·        Symmetric:  This means for any non-null reference values x and y, x.equals(y) must return true if and only if y.equals(x) returns true
Let us see how an equals() overriding can violate this rule.
public final class CaseInsensitiveString {
    private final String s;

    public CaseInsensitiveString(String s) {
        if (s == null) {
            throw new NullPointerException();
        }
        this.s = s;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof CaseInsensitiveString) {
            return s.equalsIgnoreCase(((CaseInsensitiveString) obj).s);
        }
        if (obj instanceof String) {
            return s.equalsIgnoreCase((String) obj);
        }
        return true;
    }
}

Now if we try to run the below line of code,
CaseInsensitiveString c = new CaseInsensitiveString("Test");
      String s = "test";

      System.out.println("c.equals(s):" + c.equals(s));
System.out.println("s.equals(c):" + s.equals(c));

The result will be:
c.equals(s):true
s.equals(c):false

This clearly shows how it violates rule of symmetry.  This is because String class equals() is not aware of case-insensitive strings.  In order to make this symmetric we need to do something like this:

@Override
    public boolean equals(Object obj) {

return obj instanceof CaseInsensitiveString && ((CaseInsensitiveString) obj).s.equalsIgnoreCase(s);
    }
·        Transitive:  For any non-null reference values x, y and z if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) must return true.
Let us consider a case of a superclass and a subclass.  Superclass has some properties and overrides equals. Subclass adds some more properties and try to override equals()
public class Point {
    private final int x;
    private final int y;

    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }

    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof Point)) {
            return false;
        }
        Point p = (Point) obj;
        return p.x == x && p.y == y;
    }
}

public class ColourPoint extends Point {
    private final int colour;

    public ColourPoint(int x, int y, int colour) {
        super(x, y);
        this.colour = colour;
    }

    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof ColourPoint)) {
            return false;
        }
        return super.equals(obj) && ((ColourPoint) obj).colour == colour;
    }
}

When we do,
Point p = new Point(2, 3);
     ColourPoint cp = new ColourPoint(2, 3, 8);

     System.out.println("p.equals(cp):" + p.equals(cp));
System.out.println("cp.equals(p):" + cp.equals(p));

We will get,
p.equals(cp):true
cp.equals(p):false

This pathetically fails for even symmetry.  The reason is clear.  ColourPoint’s equals() is trying to call Point’s equals() which is returning true here, thus violating the rule.  Let us see another approach,
@Override
    public boolean equals(Object obj) {
        if (!(obj instanceof Point)) {
            return false;
        }
        if (!(obj instanceof ColourPoint)) {
            return obj.equals(this);
        }
        return super.equals(obj) && ((ColourPoint) obj).colour == colour;
    }
This overriding in ColourPoint will solve symmetry but not transitivity.  How??  This is how:
Point p1 = new Point(2, 3);
      ColourPoint cp1 = new ColourPoint(2, 3, 8);
      ColourPoint cp2 = new ColourPoint(2, 3, 9);

      System.out.println("cp1.equals(p1):" + cp1.equals(p1));
      System.out.println("p1.equals(cp2):" + p1.equals(cp2));
System.out.println("cp2.equals(cp1):" + cp2.equals(cp1));

The result would be,
cp1.equals(p1):true
p1.equals(cp2):true
cp2.equals(cp1):false

Sadly, there is no way to extend an instantiable class and add a value component while preserving the equals contract, unless you are willing to forgo the benfits of object oriented-programming. 
But there can be a workaround.  Instead of having ColourPoint extend Point keep a private Point field in ColourPoint.
public class ColourPoint {
    private final Integer colour;
    private final Point point;

    public Point asPoint() {
        return point;
    }

    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof ColourPoint)) {
            return false;
        }
        ColourPoint cp = (ColourPoint) obj;
        return cp.point.equals(point) && cp.colour.equals(colour);
    }
}
Note: java.sql.Timestamp extends java.util.Date and adds a nanoseconds fieldThe equals() implementation for Timestamp does violates symmetry.  It has disclaimer stating this.
·        Consistent:  For any non-null reference values x and y, multiple invocations of x.equals(y) consistently return true or consistently return false, provided no information is changed on objects.  Best way to keep up to this is to avoid writing equals() which depends on unreliable resources.
·        For any non-null reference x.x equals(null) must return false.
We can do something like this,
@Override
public boolean equals(Object obj) {
if(obj == null) {
          return false;
      }
      ...
}

            Or this,
      @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof Point)) {
            return false;
        }
        .......
    }
    
While executing this, it will cast the object  and can throw ClassCastException, but it won’t.  Because instanceof operator will return false if it throws exception.

Now some important points to be remembered while implementing equals().
1.       Use == operator to check if the argument is a reference to this object.  This is for performance optimization.
2.      Use the instanceof operator to check if the argument has the correct type.
3.      Cast the argument to the correct type.  No need to worry about ClassCastException, because it will be preceeded by instanceof so it has to be a success.
4.      For each “significant” field in the class, check if that field of the argument matches the corresponding field of this object.
(field == null ? obj.feild == null : field.equals(o.field))

5.      Follow the rules of symmetric, transitivity and consistency.

Some Points to remember:
·        Always override hashCode when you override equals()
·        Don’t substitute another type for Object in the equals declaration.
public boolean equals(MyClass obj)                                                                                                                                                  
·        Don’t try to exaggerate.  That means only checking fields equality will do the job; don’t try hard on other things which can lead you into trouble.

**Note: You can use org.apache.commons.lang.builder.EqualsBuilder for writing a good equals().  For more information you can see http://commons.apache.org/lang/api-2.5/org/apache/commons/lang/builder/EqualsBuilder.html


{Courtesy: Effective Java - Joshua Bloch}