,

Friday 26 December 2014

Internal Working of HashMap (Immutable keys)

Immutable Key
Why Keys should be immutable in HashMap?
We have an Employee class and we are inserting the object of this class as key in HashMap.

Demo 1:
package com.immt;
import java.util.HashMap;
/**
 *
 * @author Ganesh.Rashinker
 *
 */
class Employee {
private int id;
private String name;
public Employee(int id, String name) {
super();
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Employee [id=" + id + ", name=" + name + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + id;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Employee other = (Employee) obj;
if (id != other.id)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
public class MainClass {

public static void main(String[] args) {
Employee emp1 = new Employee(1, "Robert");
HashMap<Employee, String> map = new HashMap<Employee, String>();
map.put(emp1, "First Employee");
System.out.println("map data is: "+ map);
System.out.println("map.containsKey displays: " + map.containsKey(emp1));

}
}

Output:
map data is: {Employee [id=1, name=Robert]=First Employee}
map.containsKey displays: true



On the basis of Employee objects hashcode , hash function and indexFor ,  the data goes in 9th bucket(table[9]).Below is the analysis of same. See the analysis of the same.

Demo 2:
package com.immt;
import java.util.HashMap;
/**
 *
 * @author Ganesh.Rashinker
 *
 */
class Employee {
private int id;
private String name;
public Employee(int id, String name) {
super();
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Employee [id=" + id + ", name=" + name + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + id;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Employee other = (Employee) obj;
if (id != other.id)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
public class MainClass2 {
// hash function as in HashMap
static int hash(int h) {
h ^= (h >>> 20) ^ (h >>> 12);
return h ^ (h >>> 7) ^ (h >>> 4);
}
// indexFor function as in HashMap
static int indexFor(int h, int length) {
return h & (length - 1);
}
public static void main(String[] args) {
Employee emp1 = new Employee(1, "Robert");
HashMap<Employee, String> map = new HashMap<Employee, String>();
int hashCode = emp1.hashCode();
System.out.println("hashcode value of emp1 object: " + hashCode);
int hash = hash(hashCode);
System.out.println("hash value of emp1 object: " + hash);
int bucket = indexFor(hash, 16);
System.out.println("bucket number to insert emp1 object: " + bucket);
map.put(emp1, "First Employee");
System.out.println("map data is: " + map);
System.out.println("map.containsKey displays: " + map.containsKey(emp1));
}
}

Output:
hashcode value of emp1 object: -1841844862
hash value of emp1 object: -1707535703
bucket number to insert emp1 object: 9
map data is: {Employee [id=1, name=Robert]=First Employee}
map.containsKey displays: true

The put method internally uses the hashcode of the object and calculates the hash and indexFor to find the bucket number.



It has inserted in bucket 9. When you use containsKey function , it uses the hashing functionality to find the bucket number.


Now as we have not changed the state of the object , the calulation of hashcode , hash and indexFor will return 9 and it will search in 9th bucket only and will display true.
Now let us see what exactly happens if we change the state of emp1 object.

Demo 3:
package com.immt;
import java.util.HashMap;
/**
 *
 * @author Ganesh.Rashinker
 *
 */
class Employee {
private int id;
private String name;
public Employee(int id, String name) {
super();
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Employee [id=" + id + ", name=" + name + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + id;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Employee other = (Employee) obj;
if (id != other.id)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
public class MainClass3 {
// hash function as in HashMap
static int hash(int h) {
h ^= (h >>> 20) ^ (h >>> 12);
return h ^ (h >>> 7) ^ (h >>> 4);
}
// indexFor function as in HashMap
static int indexFor(int h, int length) {
return h & (length - 1);
}
public static void main(String[] args) {
Employee emp1 = new Employee(1, "Robert");
HashMap<Employee, String> map = new HashMap<Employee, String>();
map.put(emp1, "First Employee");
System.out.println("map data is: " + map);
System.out.println("map.containsKey displays: " + map.containsKey(emp1));
emp1.setName("John");
System.out.println("map data is: " + map);
System.out.println("map.containsKey displays: " + map.containsKey(emp1));
}
}

Output:
map data is: {Employee [id=1, name=Robert]=First Employee}
map.containsKey displays: true
map data is: {Employee [id=1, name=John]=First Employee}
map.containsKey displays: false

We have changed the state of emp1 object by changing the name from Robert to John. Let us analyse , what is happening when we change the state.

Demo 4:(addition in main function only)

public static void main(String[] args) {
Employee emp1 = new Employee(1, "Robert");
HashMap<Employee, String> map = new HashMap<Employee, String>();
map.put(emp1, "First Employee");
System.out.println("map data is: " + map);
System.out.println("map.containsKey displays: " + map.containsKey(emp1));
emp1.setName("John");
System.out.println("map data is: " + map);
System.out.println("map.containsKey displays: " + map.containsKey(emp1));
//checking the below for containsKey method
int hashCode = emp1.hashCode();
System.out.println("hashcode value of emp1 object: " + hashCode);
int hash = hash(hashCode);
System.out.println("hash value of emp1 object: " + hash);
int bucket = indexFor(hash, 16);
System.out.println("bucket number to search emp1 object: " + bucket);
}

Output:
map data is: {Employee [id=1, name=Robert]=First Employee}
map.containsKey displays: true
map data is: {Employee [id=1, name=John]=First Employee}
map.containsKey displays: false
hashcode value of emp1 object: 2315531
hash value of emp1 object: 2172129
bucket number to search emp1 object: 1

The containsKey function uses hashcode , hash and indexFor function to find the bucket number where it should search for the object. The containsKey get a different hashcode , hash and indexFor values as the sate of the object is changed. It will search in a different bucket this time. So when we inserted the object the indexFor calculation was based on one state and after we change the state of the object , the hashcode changes and thus might result in searching in a different bucket and result false. Thus it is suggested that the Class whose object is inserted as key should be immutable , which means you should not be able to change the state.

To make a class Immutable in a general way  , make the class as final and member variable as private and final and remove the setter methods associated to the member variables.

Demo 4:
package com.immt;
import java.util.HashMap;
/**
 *
 * @author Ganesh.Rashinker
 *
 */
final class Employee {
private final int id;
private final String name;
public Employee(int id, String name) {
super();
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
/*public void setId(int id) {
this.id = id;
}*/
public String getName() {
return name;
}
/*public void setName(String name) {
this.name = name;
}*/
@Override
public String toString() {
return "Employee [id=" + id + ", name=" + name + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + id;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Employee other = (Employee) obj;
if (id != other.id)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
public class MainClass4 {
public static void main(String[] args) {
Employee emp1 = new Employee(1, "Robert");
HashMap<Employee, String> map = new HashMap<Employee, String>();
map.put(emp1, "First Employee");
System.out.println("map data is: " + map);
System.out.println("map.containsKey displays: " + map.containsKey(emp1));
//emp1.setName("John"); //not allowed as setters are not available in immutable class //System.out.println("map data is: " + map);
//System.out.println("map.containsKey displays: " + map.containsKey(emp1));
}
}

Output:
map data is: {Employee [id=1, name=Robert]=First Employee}
map.containsKey displays: true

Conclusion : 
The Class whose object is inserted as a key should be made immutable , which means that you should not be able to change the state of the object.







Thursday 6 November 2014

ThreadLocal is an important concept in Core Java and associated with Multithreading. 

Why use ThreadLocal ?
When you create multiple threads , there are chances of objects getting shared. There is a problem of thread interference and memory inconsistency if an object is  shared , modified and accessed by multiple threads. The solution to this is synchronization. There is one more way to avoid it , is use of ThreadLocal , where the  ThreadLocal data associated with the running thread cannot be accessed or modified from other threads. As the name suggest  , it will be local to the thread.

Let us understand the internal data-structure of ThreadLocal.

public class ThreadLocal<T> {
..
..
 static class ThreadLocalMap {
..


  private static final int INITIAL_CAPACITY = 16;
     
        private Entry[] table;
     
        private int size = 0;
     
        private int threshold; // Default to 0

The data stored in ThreadLocal is backed with map.ThreadLocal class has a static inner class ThreadLocalMap  which again has Entry as a static inner class.
static class Entry extends WeakReference<ThreadLocal> {
            /** The value associated with this ThreadLocal. */
            Object value;

            Entry(ThreadLocal k, Object v) {
                super(k);
                value = v;
            }
        }

When we use the set method of  ThreadLocal it uses ThreadLocalMap to store data.
 public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }

When we use the get method of ThreadLocal it uses ThreadLocalMap.Entry to display the data.
 public T get() {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null)
                return (T)e.value;
        }
        return setInitialValue();
    }
Let us understand the concept of ThreadLocal using a simple example.MyThreadLocal class is having HashMap object which stores data and helps to add , remove and get data.

Demo1: 

package com.a;

import java.util.HashMap;
import java.util.Map;

public class MyThreadLocal {

private static Map<Thread, Object> myThreadMap = new HashMap<Thread, Object>();

public static void add(Object object) {
myThreadMap.put(Thread.currentThread(), object);
}

public static void remove(Object object) {
myThreadMap.remove(Thread.currentThread());
}

public static Object get() {
return myThreadMap.get(Thread.currentThread());
}
}
MyThreadContext is the class which contains id and name ,  which we will store in MyThreadLocal.

package com.a;

public class MyThreadContext {
private int id;
private String name;

public MyThreadContext(int id, String name) {
super();
this.id = id;
this.name = name;
}

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

@Override
public String toString() {
return "MyThreadContext [id=" + id + ", name=" + name + "]";
}

}

We have two Runnable classes MyThread and MyThread2. The Runnable classes are used to create and add the context to the static MyThreadLocal object which is getting shared between two threads.Both the threads are having their individual context data which is added to shared ThreadLocal object. But still each thread get its local context data because the get method is displaying the data on the basis of current thread. The get method is taking the argument of current thread , which works as the key and retrieves the data associated to local thread.

package com.a;

class MyThread implements Runnable {
MyThreadContext context = new MyThreadContext(1, "ABC");

@Override
public void run() {

MyThreadLocal.add(context);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " "
+ MyThreadLocal.get());
}
}

class MyThread2 implements Runnable {
MyThreadContext context = new MyThreadContext(2, "XYZ");

@Override
public void run() {
MyThreadLocal.add(context);
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " "
+ MyThreadLocal.get());
}

}

public class MainClass {
public static void main(String[] args) {
MyThread mt = new MyThread();
MyThread2 mt2 = new MyThread2();
Thread t1 = new Thread(mt, "firstThread");
Thread t2 = new Thread(mt2, "secondThread");
t1.start();
t2.start();
}

}

In the second demo , we will use ThreadLocal object and see how it works.

Demo 2:
package com.c;

class Task1 implements Runnable {
ThreadLocal<String> tLocal;

public Task1(ThreadLocal<String> tLocal) {
super();
this.tLocal = tLocal;
}

@Override
public void run() {
tLocal.set("Task1");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

System.out.println(" Task1 transaction is : " + tLocal.get());

}

}

class Task2 implements Runnable {
ThreadLocal<String> tLocal;

public Task2(ThreadLocal<String> tLocal) {
super();
this.tLocal = tLocal;
}

@Override
public void run() {
tLocal.set("Task2");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

System.out.println(" Task2 transaction is : " + tLocal.get());

}

}

public class ThreadLocalDemo {
private static ThreadLocal<String> tLocal = new ThreadLocal<String>();

public static void main(String[] args) {

Task1 task1 = new Task1(tLocal);
Task2 task2 = new Task2(tLocal);
Thread t1 = new Thread(task1);
Thread t2 = new Thread(task2);
t1.start();
t2.start();
}
}

In the above example , Task1 and Task2  are using the same static ThreadLocal<String> object. the ThreadLocal class ineternally uses Map and the current threads data will be local to it and not avaialble to other thread.

Conclusion.
ThreadLocal class is using Map implementation internally and the get method uses the current thread as the key.

public T get() {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
and each thread has its own data associated with it.

Wednesday 8 October 2014

Java clone() method (Deep copy and Shallow copy)

Clone is a function present in Object Class. To clone an object you need to implement Cloneable interface.This topic is one of the favorite topic in interviews. Clone function is protected as it cannot be called from other classes.That is why we are using doClone function inside the Employee class.

Demo 1:
package com.a.b;
class Employee {
private int id;
private String name;
public Employee(int id, String name) {
super();
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Employee [id=" + id + ", name=" + name + "]";
}
public Object doClone() throws CloneNotSupportedException {
return this.clone();
}
}

public class MainClass {
public static void main(String[] args) {
try {
Employee object1 = new Employee(1, "Abc");
System.out.println(object1);
// cannot call object1.clone()
Employee object2 = (Employee) object1.doClone();
System.out.println(object2);
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}

The Employee class above is not implementing Cloneable interface and that is why it throws CloneNotSupportedException.

java.lang.CloneNotSupportedException: com.a.b.Employee
at java.lang.Object.clone(Native Method)
at com.a.b.Employee.doClone(MainClass.java:40)
at com.a.b.MainClass.main(MainClass.java:50)

The clone function of Object class is native. Cloneable interface is a marker interface. It is just a checkpoint for a class to implement Cloneable so that it is allowed for the object to be cloned.
We will now implement Cloneable and override clone function.

Demo 2:
package com.a.b;
class Employee implements Cloneable {
private int id;
private String name;
public Employee(int id, String name) {
super();
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Employee [id=" + id + ", name=" + name + "]";
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}

public class MainClass {
public static void main(String[] args) {
try {
Employee object1 = new Employee(1, "Abc");
System.out.println(object1);
Employee object2 = (Employee) object1.clone();
System.out.println(object2);
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
The default implementation of clone in Employee class returns super.clone() ie clone of Object class.
The above example will create the clone of the object.
But what is shallow copy and deep copy?

Employee class implements Cloneable interface. The primitive type members are deep copied.

Demo 3:(modification in main function only)
public static void main(String[] args) {
try {
Employee object1 = new Employee(1, "Abc");
System.out.println("Original object " + object1);
Employee object2 = (Employee) object1.clone();
System.out.println("Clone object " + object2);
object1.setName("Rahool");
System.out.println("After modification of name for object1 ");
System.out.println("After modification object1 " + object1);
System.out.println("After modification object2 " + object2);

} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}

What is shallow copy?
When you have any association relationship in the class and you clone the object of containing class , it will just copy the reference and not data. We have Car associated in Employee class.

Demo 4:
package com.a.b;
class Car {
private String brand;
private String model;
public Car(String brand, String model) {
super();
this.brand = brand;
this.model = model;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
@Override
public String toString() {
return "Car [brand=" + brand + ", model=" + model + "]";
}
}

class Employee implements Cloneable {
private int id;
private String name;
public Car car;// association relationship
public Employee(int id, String name, Car car) {
super();
this.id = id;
this.name = name;
this.car = car;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Employee [carmodel=" + car.getModel() + "car brand="
+ car.getBrand() + ", id=" + id + ", name=" + name + "]";
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}

public class MainClass {
public static void main(String[] args) {
try {
Car car = new Car("Zonita", "Stromy");
Employee object1 = new Employee(1, "John", car);
System.out.println("Original object " + object1);
Employee object2 = (Employee) object1.clone();
System.out.println("Clone object " + object2);
// deep copy
object1.setName("Rahool");
System.out.println("After modification of name for object1(deep copy) ");
System.out.println("After modification object1 " + object1);// name Rahool
System.out.println("After modification object2 " + object2);// name John
                        //shallow copy
object1.car.setModel("Twinkle");
System.out.println("After modification of Car for object1(shallow copy) ");
System.out.println("After modification object1 " + object1);// car model Twinkle
System.out.println("After modification object2 " + object2);// car model Twinkle

} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}

Output:
Original object Employee [carmodel=Stromycar brand=Zonita, id=1, name=John]
Clone object Employee [carmodel=Stromycar brand=Zonita, id=1, name=John]
After modification of name for object1(deep copy)
After modification object1 Employee [carmodel=Stromycar brand=Zonita, id=1, name=Rahool]
After modification object2 Employee [carmodel=Stromycar brand=Zonita, id=1, name=John]
After modification of Car for object1(shallow copy)
After modification object1 Employee [carmodel=Twinklecar brand=Zonita, id=1, name=Rahool]
After modification object2 Employee [carmodel=Twinklecar brand=Zonita, id=1, name=John]

Even though we are changing the car model using object 1 , the modification is getting reflected for object2 as well. This is becuase of shallow copy where it is copying only the reference.
Now the question is how will you achieve deep copy even for associated members.

You can achieve this by two ways
1) Implementing Cloneable for associated class.
2) Serialization
(You can also return a new object from clone but it is not copy)

Implementing Cloneable for associated class
Implementing Cloneable interface for associated class Car will facilitate deep copy of car members also. We need to write business logic in clone function of Employe class so that we have a deep copy.

Demo 5:
package com.a.b;
class Car implements Cloneable {
private String brand;
private String model;
public Car(String brand, String model) {
super();
this.brand = brand;
this.model = model;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
@Override
protected Object clone() throws CloneNotSupportedException {
// TODO Auto-generated method stub
return super.clone();
}
@Override
public String toString() {
return "Car [brand=" + brand + ", model=" + model + "]";
}
}

class Employee implements Cloneable {
private int id;
private String name;
public Car car;
public Employee(int id, String name, Car car) {
super();
this.id = id;
this.name = name;
this.car = car;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Employee [carmodel=" + car.getModel() + "car brand="
+ car.getBrand() + ", id=" + id + ", name=" + name + "]";
}
@Override
protected Object clone() throws CloneNotSupportedException {
// deep clone of Employee members
Employee emp = (Employee) super.clone();
// deep clone of Car members
emp.car = (Car) car.clone();
return emp;
// return super.clone();
}
}

public class MainClass {
public static void main(String[] args) {
try {
Car car = new Car("Zonita", "Stromy");
Employee object1 = new Employee(1, "John", car);
System.out.println("Original object " + object1);
Employee object2 = (Employee) object1.clone();
System.out.println("Clone object " + object2);
// deep copy
object1.setName("Rahool");
System.out.println("After modification of name for object1(deep copy) ");
System.out.println("After modification object1 " + object1);// name Rahool
System.out.println("After modification object2 " + object2);// name John
                        //deep copy
object1.car.setModel("Twinkle");
System.out.println("After modification of Car for object1(associated object is also deep copied now) ");
System.out.println("After modification object1 " + object1);// car model Twinkle
System.out.println("After modification object2 " + object2);// car model Stromy
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}

Output:
Original object Employee [carmodel=Stromycar brand=Zonita, id=1, name=John]
Clone object Employee [carmodel=Stromycar brand=Zonita, id=1, name=John]
After modification of name for object1(deep copy) 
After modification object1 Employee [carmodel=Stromycar brand=Zonita, id=1, name=Rahool]
After modification object2 Employee [carmodel=Stromycar brand=Zonita, id=1, name=John]
After modification of Car for object1(associated object is also deep copied now) 
After modification object1 Employee [carmodel=Twinklecar brand=Zonita, id=1, name=Rahool]
After modification object2 Employee [carmodel=Stromycar brand=Zonita, id=1, name=John]

Serialization
You can use serialization to achieve deep copy.We have added two functions public void doSerialize(Employee emp) and public Object doDeSerialize() for the serialization process.

Demo 6:
package com.a.b.c;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
class Car implements Serializable {
private static final long serialVersionUID = 1L;
private String brand;
private String model;
public Car(String brand, String model) {
super();
this.brand = brand;
this.model = model;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
@Override
public String toString() {
return "Car [brand=" + brand + ", model=" + model + "]";
}
}

class Employee implements Cloneable, Serializable {
private int id;
private String name;
public Car car;
public Employee(int id, String name, Car car) {
super();
this.id = id;
this.name = name;
this.car = car;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Employee [carmodel=" + car.getModel() + "car brand="
+ car.getBrand() + ", id=" + id + ", name=" + name + "]";
}
public void doSerialize(Employee emp) {
ObjectOutputStream ois = null;
try {
ois = new ObjectOutputStream(new FileOutputStream("D://myFile.ser"));
ois.writeObject(emp);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public Object doDeSerialize() {
Object obj = null;
ObjectInputStream ois = null;
try {
ois = new ObjectInputStream(new FileInputStream("D://myFile.ser"));
obj = ois.readObject();

} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
try {
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return obj;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return doDeSerialize();
}
}

public class MainClass {
public static void main(String[] args) {
try {
Car car = new Car("Zonita", "Stromy");
Employee object1 = new Employee(1, "John", car);
object1.doSerialize(object1);
System.out.println("Original object " + object1);
Employee object2 = (Employee) object1.clone();
System.out.println("Clone object " + object2);
// deep copy
object1.setName("Rahool");
System.out.println("After modification of name for object1(deep copy) ");
System.out.println("After modification object1 " + object1);// name Rahool
System.out.println("After modification object2 " + object2);// name John
//deep copy
object1.car.setModel("Twinkle");
System.out.println("After modification of Car for object1(deep copy) ");
System.out.println("After modification object1 " + object1);// car model Twinkle
System.out.println("After modification object2 " + object2);// car model Stromy
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}

public class MainClass {
public static void main(String[] args) {
try {
Car car = new Car("Zonita", "Stromy");
Employee object1 = new Employee(1, "John", car);
object1.doSerialize(object1);
System.out.println("Original object " + object1);
Employee object2 = (Employee) object1.clone();
System.out.println("Clone object " + object2);
// deep copy
object1.setName("Rahool");
System.out.println("After modification of name for object1(deep copy) ");
System.out.println("After modification object1 " + object1);// name Rahool
System.out.println("After modification object2 " + object2);// name John
//deep copy
object1.car.setModel("Twinkle");
System.out.println("After modification of Car for object1(deep copy) ");
System.out.println("After modification object1 " + object1);// car model Twinkle
System.out.println("After modification object2 " + object2);// car model Stromy
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}

Output:
Original object Employee [carmodel=Stromycar brand=Zonita, id=1, name=John]
Clone object Employee [carmodel=Stromycar brand=Zonita, id=1, name=John]
After modification of name for object1(deep copy) 
After modification object1 Employee [carmodel=Stromycar brand=Zonita, id=1, name=Rahool]
After modification object2 Employee [carmodel=Stromycar brand=Zonita, id=1, name=John]
After modification of Car for object1(deep copy) 
After modification object1 Employee [carmodel=Twinklecar brand=Zonita, id=1, name=Rahool]
After modification object2 Employee [carmodel=Stromycar brand=Zonita, id=1, name=John]

Conclusion : The class implementing Cloneable interface has its primitive type deep copied and associated type shallow copied and in order to make everything deep copy you can go for either cloning the associated class(Car) or serialization of the containing class(Employee).

Tuesday 30 September 2014

Internals of ArrayList (Part 2)

In the last tutorial ,we explored on the internal data structure and few other technical stuff including add method.In this tutorial we will try to understand why ArrayList is not preferred when you need to do modifications in list.
In this tutorial we will continue with add method. Instead of
list.add("data11");
which will insert the data at end , we will use
list.add(5, "data11");
which will add data in between the list.

Demo4
import java.util.ArrayList;

/**
 *
 * @author Ganesh.Rashinker
 *
 */
public class Demo4 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
for (int i = 1; i <= 10; i++) {
list.add("data" + i);
}
// insert 11th element at position 5th index
list.add(5, "data11");
}
}



The list is already having 10 elements and the 11th element is added at 5th index. As the initial capacity was 10 and which is full , a new array of capacity 16 will be created using ensureCapacity function. After the ensure capacity function, elementData is referring to new array of capacity 16.


After ensure capacity , System.arraycopy function copies the data from 5th index till the end of the list size and replaces the data from index 6.



so you have "data6"  at index 5 and 6. The next statement

elementData[index] = element;

actualy replaces "data6" with the new data "data11".

So this is how shifting of data happens. So Imagine you have ArrayList having size 1000 and you add a new element at index 5.

Conclusion: ArrayList is preferred when there are more reads and LinkedList is preferred where you have more modifications.This is one of the favorite interview question. ArrayList is expensive when you are modifying data  , we have already seen if you want to add data in between it need to shift the entire data from that index till the end of list. In this scenario , LinkedList is comparatively cheaper as memory would be allocated for new Node and the pointers of previous node and next node will be adjusted. There will be no other change in the entire LinkedList.

Thursday 7 August 2014

Internal Working of HashSet

HashSet in java
HashSet implements Set interface.It is a collection that contains no duplicate elements. HashSet is unordered.
Let us undertsand Internal working of HashSet using the below example. The example contains Employee class with two members id and name. We are implementing the hashcode , equals and toString methods.

Demo 1:

import java.util.HashSet;

/**
 *
 * @author Ganesh.Rashinker
 *
 */
class Employee {
private int id;
private String name;

public Employee(int id, String name) {
super();
this.id = id;
this.name = name;
}

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + id;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}

@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Employee other = (Employee) obj;
if (id != other.id)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}

@Override
public String toString() {
return "Employee [id=" + id + ", name=" + name + "]";
}
}

public class MainClass {

public static void main(String[] args) {
HashSet<Employee> set = new HashSet<Employee>();
Employee emp1 = new Employee(1, "Jack");
Employee emp2 = new Employee(2, "Robert");
Employee emp3 = new Employee(2, "Nancy");
Employee emp4 = new Employee(2, "Tom");
set.add(emp1);
set.add(emp2);
set.add(emp3);
set.add(emp4);
System.out.println(set);
}

}
Output:
[Employee [id=2, name=Robert], Employee [id=1, name=Jack], Employee [id=2, name=Nancy], Employee [id=2, name=Tom]]

HashSet uses HashMap internally. The value added to set is added as a key to HashMap and the value is a dummy static object. the above output shows that the data is unordered. The add method of HashSet call the put  method of HashMap internally.








Conclusion: HashSet uses HashMap internally and so it is best practice to implement hashcode and equals for the class , whose object is added in HashSet.The element of set is stored as key and the static object(dummy Object) of Object class is stored as value of HashMap.