Tuesday, December 29, 2009

What is difference between HashMap and HashTable?

Both collections implements Map. Both collections store value as key-value pairs. The key differences between the two are

1. Access to the Hashtable is synchronized on the table while access to the HashMap isn’t. You can add it, but it isn’t there by default.

2. Another difference is that iterator in the HashMap is fail-safe while the enumerator for the Hashtable isn’t. If you change the map while iterating, you’ll know. • Fail-safe – “if the Hashtable is structurally modified at any time after the iterator is created, in any way except through the iterator’s own remove method, the iterator will throw a ConcurrentModificationException”

3. HashMap permits null values and only one null key, while Hashtable doesn’t allow key or value as null.

Use of hashcode() and equals() in java

Use of hashCode() and equals().

Object class provides two methods hashcode() and equals() to represent the identity of an object. It is a common convention that if one method is overridden then other should also be implemented.

Before explaining why, let see what the contract these two methods hold. As per the Java API documentation:

*
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.

Now, consider an example where the key used to store the in Hashmap is an Integer. Consider that Integer class doesn’t implement hashcode() method. The code would look like:

map.put(new Integer(5),”Value1″);
String value = (String) map.get(new Integer(5));
System.out.println(value);
//Output : Value is null

Null value will be displayed since the hashcode() method returns a different hash value for the Integer object created at line 2and JVM tries to search for the object at different location.

Now if the integer class has hashcode() method like:

public int hashCode(){
return value;
}

Everytime the new Integer object is created with same integer value passed; the Integer object will return the same hash value. Once the same hash value is returned, JVM will go to the same memory address every time and if in case there are more than one objects present for the same hash value it will use equals() method to identify the correct object.

Another step of caution that needs to be taken is that while implementing the hashcode() method the fields that are present in the hashcode() should not be the one which could change the state of object.

Consider the example:

public class FourWheeler implements Vehicle {



private String name;

private int purchaseValue;

private int noOfTyres;

public FourWheeler(){}



public FourWheeler(String name, int purchaseValue) {

this.name = name;

this.purchaseValue = purchaseValue;

}

public void setPurchaseValue(int purchaseValue) {

this.purchaseValue = purchaseValue;

}



@Override

public int hashCode() {

final int prime = 31;

int result = 1;

result = prime * result + ((name == null) ? 0 : name.hashCode());

result = prime * result + purchaseValue;

return result;

}

}

FourWheeler fourWObj = new FourWheeler(“Santro”,”333333);
map.put(fourWObj,”Hyundai);
fourWObj.setPurchaseValue(“555555)
System.out.println(map.get(fourWObj));
//Output: null

We can see that inspite of passing the same object the value returned is null. This is because the hashcode() returned on evaluation will be different since the purchaseValue is set to ‘555555’ from ‘333333’. Hence we can conclude that the hashcode() should contain fields that doesn’t change the state of object.

One compatible, but not all that useful, way to define hashCode() is like this:

public int hashcode(){
return 0;
}

This approach will yield bad performance for the HashMap. The conclusion which can be made is that the hashcode() should(not must) return the same value if the objects are equal. If the objects are not equal then it must return different value.

Overriding equals() method

Consider the example:

public class StringHelper {



private String inputString;



public StringHelper(String string) {

inputString=string;

}



@Override

public int hashCode() {

return inputString.length();

}





public static void main(String[] args) {



StringHelper helperObj = new StringHelper(“string”);

StringHelper helperObj1 = new StringHelper(“string”);

if(helperObj.hashCode() == helperObj1.hashCode()){

System.out.println(“HashCode are equal”);

}

if(helperObj.equals(helperObj1)){

System.out.println(“Objects are equal”);

}else{

System.out.println(“Objects are not equal”);

}



}



public String getInputString() {

return inputString;

}



// Output:
HashCode are equal
Objects are not equal

We can see that even though the StringHelper object contains the same value the equals method has returned false but the hashcode method has return true value.

To prevent this inconsistency, we should make sure that we override both methods such that the contract between both methods doesn’t fail.

Steps that need to be taken into consideration while implementing equals method.

1. Use the == operator to check if the argument is a reference to this object. If so, return true. This is just a performance optimization, but one that is worth doing if the comparison is potentially expensive.

2. Use the instanceof operator to check if the argument has the correct type.

If not, return false. Typically, the correct type is the class in which the method occurs. Occasionally, it is some interface implemented by this class. Use an interface if the class implements an interface that refines the equals contract to permit comparisons across classes that implement the interface. Collection interfaces such as Set, List, Map, and Map.Entry have this property.

3. Cast the argument to the correct type. Because this cast was preceded by an instanceof test, it is guaranteed to succeed.

4. For each “significant” field in the class, checks if that field of the argument matches the corresponding field of this object. If all these tests succeed, return true; otherwise, return false

5. When you are finished writing your equals method, ask yourself three questions: Is it symmetric? Is it transitive? Is it consistent?

The correct implementation if equals method for the StringHelper class could be:

@Override

public boolean equals(Object obj) {

if (this == obj)

return true;

if (obj == null)

return false;

if (getClass() != obj.getClass())

return false;

final StringHelper other = (StringHelper) obj;

if (inputString == null) {

if (other.inputString != null)

return false;

} else if (!inputString.equals(other.inputString))

return false;

return true;

}

How HashSet works?

Yes, earlier i wasnt sure how HashSet is created internally and which data structure is used. But when I looked at the class implemenation i was surprised because of following features i noticed:

Hashset is used to store the unique elements, in which their is no gurantee of the iteration order.

Hashset internally use HashMap .

Elements passed to Hashset are stored as a key of the HashMap with null as value. Since the objects passed to set are key so no extra check is done to identify duplicates. For eg after adding integer 1 and 2 if i add 1 again, no check is performed to identify whether 1 is present or not. The hashset simply performs the put with the same value( ‘1′) in this case as key.

Similariy when an element is removed from the Set the internal HashMap remove method is called.

So HashSet data structure is nothing but a HashMap with objects as key.

HashSet Implemenation from java.util package

1. public HashSet() {
map = new HashMap();
}
2. public boolean add(E o) {
return map.put(o, PRESENT)==null;
}
3. /**
* Removes the specified element from this set if it is present.
*
* @param o object to be removed from this set, if present.
* @return true if the set contained the specified element.
*/
public boolean remove(Object o) {
return map.remove(o)==PRESENT;
}

How to create Immutable Class?

mmutable class is a class which once created, it’s contents can not be changed and cannot be inherited. Immutable objects are the objects of immutable class whose state can not be changed once constructed. e.g. String class

To create an immutable class following steps should be followed:

1. Create a final class.
2. Set the values of properties using constructor only.
3. Make the properties of the class final and private
4. Do not provide any setters for these properties.
5. If the instance fields include references to mutable objects, don’t allow those objects to be changed:
1. Don’t provide methods that modify the mutable objects.
2. Don’t share references to the mutable objects. Never store references to external, mutable objects passed to the constructor; if necessary, create copies, and store references to the copies. Similarly, create copies of your internal mutable objects when necessary to avoid returning the originals in your methods.

E.g.
public final class FinalPersonClass {

private final String name;
private final int age;

public FinalPersonClass(final String name, final int age) {
super();
this.name = name;
this.age = age;
}
public int getAge() {
return age;
}
public String getName() {
return name;
}
}

All wrapper classes in java.lang are immutable –
String, Integer, Boolean, Character, Byte, Short, Long, Float, Double, BigDecimal, BigInteger

java.lang.OutOfMemoryError while doing ant build?

While doing an ant build sometimes it happen that a user may get the OutOfMemoryError. This is mainly because the heap size of Java JVM is less. This heap size can be increased. But caution that the heap size of java JVM which is running through Ant has to be increased and not of the JVM of Jdk 1.x .

To increase the heap size of JVM in ant ,open the file ant.cmd present in Ant/bin folder.

Change following line

“%_JAVACMD%” %ANT_OPTS% -classpath “%ANT_HOME%\lib\ant-launcher.jar” “-Dant.home=%ANT_HOME%” org.apache.tools.ant.launch.Launcher %ANT_ARGS% -cp “%CLASSPATH%” %ANT_CMD_LINE_ARGS%

“%_JAVACMD%” -Xms512m -Xmx1024m %ANT_OPTS% -classpath “%ANT_HOME%\lib\ant-launcher.jar” “-Dant.home=%ANT_HOME%” org.apache.tools.ant.launch.Launcher %ANT_ARGS% -cp “%CLASSPATH%” %ANT_CMD_LINE_ARGS%
Rate This