Monday, 6 October 2014

Java Enum and its different uses

Enums :-

  • are set of constants.
  • special type of class that extends java.lang.Enum
  • implements Comparable and Serializable, and singleton by default. Hence, we can compare  enum with == operator.
  • enforce compile time error check.

Simple implementation of enum

public enum Status {
ACT,
PEN,
ARC,
DAC
}

Here ACT, PEN, ARC, DAC all are constant for enum Status.


Enum with values 

We can provide value to enum at the time their creation, for this we need a private constructor and a private member variable.

public enum Status {
ACT("ACTIVE"),
PEN("PENDING"),
ARC("ARCHIVE"),
DAC("DEACTIVE");

private String value;
private Status(String value){
this.value = value;
}
public String getValue() {
return value;
}
}

usage:- Status.ACT.getValue();

Enum with abstract method

public enum Status {
ACT{
public String getDescription()
{
return "ACTIVE";
}
},
PEN{
public String getDescription()
{
return "PENDING";
}
},
ARC{
public String getDescription(){
return "ARCHIVE";
}
},
DAC{
public String getDescription(){
return "DEACTIVE";
}
};
public abstract String getDescription();
}

usage:- Status.ACT.getDescription();


Printing entire Enum 

for(Status s : Status.values()){
System.out.println((s.name()));
}


Handling IllegalArgumentException with Enum

Enum can throw illegalArguementException when we try to get value of anything which is not a part of enum set using valueOf().
This feature can be used to determine whether a particular value is a part of  enum set or not.
See below implementation.

public enum Status {
ACT,
PEN,
ARC,
DAC
}

public class ValidateStatus{

static String checkValidStatus(String status){
try{
Status.valueOf(status);
}
catch(IllegalArgumentException e){
return "Not a valid status";
}
return "valid status";
}
public static void main(String[] args) {

System.out.println(checkValidStatus("ACT"));
System.out.println(checkValidStatus("DEC"));
}

}

output:-
valid status
Not a valid status



Sunday, 5 October 2014

Different ways of iterating Map and their performance

There are 4 ways using which we can iterate through a map. These 4 ways are based on entrySet() and keySet().
Any collection can be iterated using for each loop and iterator. For map also, iteration is done using these two techniques.

Method 1: keySet() with for each loop.
Method 2: keySet() with iterator().
Method 3: entrySet() with for each loop.
Method 4: entrySet() with iterator().

Let us see each method one by one and their cost of performance :

Create a map for 100000 objects.

Map<Integer,String> map = new HashMap<Integer,String>();
for(int i = 0; i<100000;i++)
{
     map.put(i,"object"+i);
}

Now we have created a map for 100000 objects, let iterate this map using each method one by one.

Method 1 : keySet() with for each loop

   long start = System.currentTimeMillis();
Set<Integer> keySet = map.keySet();
for(Integer key : keySet)
  {
String value = map.get(key);
}
long end = System.currentTimeMillis();
System.out.println("Method 1 takes "+(end-start)+" milliseconds");


Method 2: keySet() with iterator()

long start = System.currentTimeMillis();
Set<Integer> keySet = map.keySet();
Iterator<Integer> iterator = keySet.iterator();
while(iterator.hasNext())
{
Integer key = iterator.next();
String value = map.get(key);
}
long end = System.currentTimeMillis();

System.out.println("Method 2 takes "+(end-start)+" milliseconds");


Method 3: entrySet() with for each loop

long start = System.currentTimeMillis();
Set<Map.Entry<Integer, String>> entrySet = map.entrySet();
for(Map.Entry entry : entrySet)
{
Integer key = entry.getKey();
String value = entry.getValue();
}
long end = System.currentTimeMillis();

System.out.println("Method 3 takes "+(end-start)+" milliseconds");


Method 4: entrySet() with iterator()

long start = System.currentTimeMillis();
Set<Map.Entry<Integer, String>> entrySet = map.entrySet();
Iterator<Map.Entry<Integer, String>> iterator = entrySet.iterator();
while(iterator.hasNext())
{
Map.Entry entry = iterator.next();
Integer key = entry.getKey();
String value = entry.getValue();
}
long end = System.currentTimeMillis();

System.out.println("Method 4 takes "+(end-start)+" milliseconds");

Output:-
Method 1 takes 109 milliseconds
Method 2 takes 168 milliseconds
Method 3 takes 63 milliseconds
Method 4 takes 68 milliseconds

From this observation, it is clear that entrySet() is faster than keySet(). So Method 1 and Method 2 are ruled out from the race.

Now to decide which to be used between Method 3 and method 4, we need to see our requirements.
If we want to modify the content of map during its iteration, then go for iterator(), because any attempt made to modify the content of map during its iteration using for each loop, will result in java.util.ConcurrentModificationException.

Set<Map.Entry<Integer, String>> entrySet = map.entrySet();
for(Map.Entry entry : entrySet)
{
map.remove(entry.getKey());  // throws run time exception here.
String value = entry.getValue();
}
long end = System.currentTimeMillis();



Using iterator(), one can modify the content of map during its iteration.

Set<Map.Entry<Integer, String>> entrySet = map.entrySet();
Iterator<Map.Entry<Integer, String>> iterator = entrySet.iterator();
while(iterator.hasNext())
{
Map.Entry entry = iterator.next();
iterator.remove();    //valid here
}