Monday, May 12, 2014

How to create immutable class in Java

What is an immutable class?
An immutable class is a class which once created, its contents can not be changed. Modification of the object will lead to creation of new instances. e.g. String class

How to create an immutable class?
Below are important guidelines to create an immutable class.
  • Declare the class as final so it can’t be extended.
  • Make the properties of the class final and private so that their values can be assigned once and they are not directly accessible from outside world.
  • Set the values of properties using constructor only.
  • Do not provide any setters for these properties.
  • If the class has any mutable object fields, then they must be defensively copied when they pass between the class and its caller.




public final class Student {

     private final String name;
     private final int age;
     private final List books;

     public Person(String name, int age, List books) {
         this.name = name;
         this.age = age;
         this.books = new ArrayList(this.books);
     }

     public String getName() {
         return this.name;
     }

     public int getAge() {
         return this.age;
     }

     public Collection getBooks() {
         return Collections.unmodifiableList(this.books);
     }
}

What are the benefits of using immutable classes?
Benefits are as follows:
1) Immutable objects are automatically thread-safe, the overhead caused due to use of synchronisation is avoided.
2) Once created the state of the immutable object can not be changed so there is no possibility of them getting into an inconsistent state.
3) The best use of the immutable objects is as the keys of a map.


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

Friday, April 25, 2014

Difference between comparable and comparator interface

Natural ordering a collection can be done by implementing Comparable interface. By implementing Comparable, sorting an array of objects or a collection (List etc) is as simple as:

Arrays.sort(myArray);
Collections.sort(myCollection);

For classes that don’t implement Comparable interface, or when one needs even more control over ordering based on multiple attributes, a Comparator interface should be used. Let's try to sort by implementing both the interfaces.

Sorting using Comparable interface

Employee represents the entity that needs to be sorted.

Employee.java
public class Employee implements Comparable {
private int employeeId;
private String employeeName;
public Employee(int employeeId, String employeeName) {
this.employeeId = employeeId;
this.employeeName = employeeName;
}

@Override
public int compareTo(Employee emp) {
Employee otherEmployee = (Employee) emp;
return (this.employeeId < otherEmployee.employeeId) ? -1 : (this.employeeId > otherEmployee.employeeId) ? 1 : 0;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append("Employee [");
sb.append("employeeId=").append(employeeId);
sb.append(", employeeName=").append(employeeName);
sb.append("]");
return sb.toString();
}
}


SortEmployees.java
public class SortEmployees {

public static void main(String[] args) {
List employeeList = new ArrayList();
employeeList.add(new Employee(1, "Sam"));
employeeList.add(new Employee(2, "John"));
employeeList.add(new Employee(1, "Raun"));
Collections.sort(employeeList); // sorts using compareTo method
for (Employee employee : employeeList) {
System.out.println(employee);
}
}
}

Output: 
Employee [employeeId=1, employeeName=Sam]
Employee [employeeId=1, employeeName=Raun]
Employee [employeeId=2, employeeName=John]


Sorting using Comparable interface

Here, we need a new class which will implement the Comparator interface and its instance will be passed by sorting the collection of employees list.

EmployeeComparator.java
public class EmployeeComparator implements Comparator {

@Override
public int compare(Employee obj1, Employee obj2) {
int result = 0;

Employee emp1 = (Employee) obj1;
Employee emp2 = (Employee) obj2;

result = (emp1.getEmployeeId() < emp2.getEmployeeId()) ? -1 : (emp1.getEmployeeId() > emp2.getEmployeeId()) ? 1 : 0;

if(result == 0){
result = emp1.getEmployeeName().compareTo(emp2.getEmployeeName());
}
return result;
}
}

SortEmployees.java
public class SortEmployees {

public static void main(String[] args) {
List employeeList = new ArrayList();
employeeList.add(new Employee(1, "Sam"));
employeeList.add(new Employee(2, "John"));
employeeList.add(new Employee(1, "Raun"));

Collections.sort(employeeList, new EmployeeComparator());
for (Employee employee : employeeList) {
System.out.println(employee);
}
}
}


Output: 
Employee [employeeId=1, employeeName=Raun]
Employee [employeeId=1, employeeName=Sam]
Employee [employeeId=2, employeeName=John]

Friday, April 18, 2014

SVN : Merge branch to trunk

Merging a branch to trunk in SVN is not as straight forward as in the case of GIT. It's a bit lengthy process as it needs a number of steps to be followed. Below the series of the steps one should follow.

1. Check out a copy of trunk:
   svn co svn+ssh://server/path/to/trunk

2. Check out a copy of the branch you are going to merge:
   svn co svn+ssh://server/path/to/branch/myFeatureBranch

3. Change your current working directory to “
myFeatureBranch”. Find the revision “myFeatureBranch” began at:
   svn log --stop-on-copy

This should display back to you the changes that have been made back to the point the feature branch was cut. Remember that number (should be rXXX, where XXX is the revision number).

4. Change your current working directory to trunk and perform an SVN update:
   svn up

This will update your copy of trunk to the most recent version, and tell you the revision you are at. Make note of that number as well (should say “At revision YYY” where YYY is the second number you need to remember).

5. Now we can perform an SVN merge:
   svn merge -rXXX:YYY svn+ssh://server/path/to/branch/
myFeatureBranch

This will put all updates into your current working directory for trunk. Resolve any conflicts that arose during the merge

6. Check in the results:
   svn ci -m "MERGING
myFeatureBranch [XXX]:[YYY] into trunk"