Monday, April 4, 2011

How to use java annotations

                            Annotations are some of the major introduction that came with JDK 5 . And now most of the developers are trend to use annotations. So I decide to write this article about annotations but this may not be suitable for experts who try to discover more with annotations because this article is most suitable for people who does not familiar with annotations.
Before we go further it is better to discuss some of the key factors of java annotations.
  • java annotations were introduced to the java world with JDK 5 (JSR 175)
  • Annotations are providing a strong mechanism to define meta data .
  • It improve readability of the code .
  • Can use in every where inside the code
  • Easy to define (no need of long set of configurations)
Basically there are three types of annotations
  1. Multi value annotations
  2. Single value annotations
  3. Marker annotations

It is easy to understand other two types of annotations if we define Multi value annotations so lets begin our new annotations as a multi value.
/**
 * @author amith jayasekara
 *         
 *         simple multi value annotation
 */
@interface MultivalueAnotaion {

    String message();
    //this will set mata data print number to 23 if there is
    // no explicitly deceleration

    int printNumber() default 23;

}
 

                          We define annotation with @interface . Then we can define over own methods inside the annotation class but keep in mind as interfaces annotation cannot have methods with body . So keep body of the method as empty .There are some restrictions while define method inside annotation.
  • Return type of method should be a primitive value or an Object type.
  • Or it can be a enum or other annotation type.
  • Or it can be array of above types .
  • No other return types are allows to use with annotation methods.
  • And there can not be generics in side annotations.
                         We can define default value for methods with default key word and they will be used if we does not define while using the annotation.

Improving above annotation .
              We can improve annotation with following two properties .
  • What extend the this annotation is retained .
  • Where we use this annotation.
Define what extend that this annotation will be retain.

                      To do that we can use another pre defined annotation called @Retention. There are 3 retaliation policies are defined with this annotation.
  • RetentionPolicy.RUNTIME
Retain annotation definition during the runtime (so java runtime can access meta data)
  • RetentionPolicy.CLASS(default type)
Retain annotation definition in the class file.
  • RetentionPolicy.SOURCE
Retain annotation definition in source file

Define where to use annotation.
                    To do that we can user another pre defined annotation called @Target . Follow are available options . Note that we can define more that one definition but it will give compiler error if we used same definition more that one inside the Element type array.
example :
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.FIELD})
this will give compile errors
check out available options for Element types here

So now we see the improved version of our multi valued annotation.

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @author amith jayasekara
 *        
 *         simple multi value annotation that retain in runtime and that
 *         can be used in class level
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
    @interface MultivalueAnotaion {

    String message();
    //this will set mata data print number to 23 if there is
    // no explicitly deceleration

    int printNumber() default 23;

}

                    Now we know how to define a simple annotation but it is no use if we don't know how to use this annotation . Follow is a sample code that define the usage of the annotation.

import java.lang.annotation.Annotation;

/**
 * @author amith jayasekara
 *         sample code for testing annotation in runtime of the programme
 */
@MultivalueAnotaion(message = "sample message")
public class MultivalueAnnotationTest {

    public static void main(String[] args) {
        //we create a object of the class
        MultivalueAnnotationTest test = new MultivalueAnnotationTest();

        //check is annotation is available
        if (test.getClass().isAnnotationPresent(MultivalueAnotaion.class)) {
            MultivalueAnotaion ma = test.getClass().getAnnotation(MultivalueAnotaion.class);
            System.out.println("annotation message " + ma.message());
            System.out.println("annotation print number " + ma.printNumber());
        }
    }
}

Single value annotation
 There is only method definition inside the annotation class.


import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @author amith jayasekara
 *         single value annotation
 *         retain till runtime and only be able to apply for method level
 */

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
    @interface SingleValueAnnotation {
    boolean isPrintMessage() default true;
}

sample usage
import java.lang.reflect.Method;

/**
 * @author amith jayasekara
 */
public class SingleValueAnnotationTest {
    @SingleValueAnnotation
    public static void annotatedMethod() {
        SingleValueAnnotationTest st = new SingleValueAnnotationTest();
        Class cls = st.getClass();
        try {
            Method method = cls.getMethod("annotatedMethod");
            SingleValueAnnotation ano = method.getAnnotation(SingleValueAnnotation.class);
            System.out.println("is print message " + ano.isPrintMessage());
        } catch (NoSuchMethodException e) {
            System.out.println("no method found");
        }
    }

    public static void main(String[] args) {
        annotatedMethod();
    }
}



Marker annotation
                      If the annotation body does not contain any method that type of annotations are known as marker annotation . And their behavior is very much similar to marker interfaces.
Follow is a sample marker annotation and sample usage code for that annotation

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


/**
 * marker annotations
 * this annotation is available in runtime and  the target is class level
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
    @interface MyMarker {
}

sample usage class
/**
 * @author amith jayasekara
 */
public class MarkerAnoTest {
    public static void main(String[] args) {
        MarkerClass mark = new MarkerClass();
        if (mark.getClass().isAnnotationPresent(MyMarker.class)) {
            System.out.println("Mark is marked with marker annotation");
        }
    }
} 
 

There are many pre defined annotation are available with java if you are really interesting with what are they go through follow links .
devx.com

Sunday, February 27, 2011

Optimizing HashMap and HashSet with load factor


                                  Java Collection interface is one of the most used interface in java, it allows developers to choses variety of flexible data structures. Among those data structures one of the mostly using data structure is HashMap and HashSet as well.The question is are we getting full usage from that most commonly used data structure . This topic will cover some of the main details that you may have forgotten about those two data structure. And keep in mind I'm not going to discuss about when to use those two or what are the functionalities of this two in this artcle.
                              Before we going to the topic it is better to know what are the back ground of those two data structures. Basically HashMap and HashSet are derive from one of the most conman data structure called HashTable so it is better to know why we implement HashTable type data structures. The reason for that is speed of searching particular element . In hashing we try to search a element in a constant time “O(1)” . And the load factor of HashTable directly effect to the searching speed 

                               number of stored elements in the table
      load factor =----------------------------------------------------------------------
                                            size of the hash table 

                            If we able to maintain load factor from range of .7 to .75 we are able to search element form the constant time. But keep in mind the load factor is not the only thing that effect to the searching speed of a element in the hast table.

                           Now we check out how this load factor combine with HashTable and HashMap. In the Hashtable documentation they have mentioned how much load factor we have to maintain to get optimal time for searching a element and they strongly recommended to maintain load factor to 0.75
(check java doc for HashMap and HashSet)

So now its is developers responsibility to select a proper intercalation size for the HashMap or HashTable we can do that easily by using constructor
example
Assume there are 750 Person details


Now we can assume we will get O(1) searching time for a finding person from the data structure.

What happen if load factor exceed than initialize? 
Both HashMap and HashSet behave in same way so im using HashMap as example 

HashMap()
          Constructs an empty HashMap with the default initial capacity (16) and the default load factor (0.75).
HashMap(int initialCapacity)
          Constructs an empty HashMap with the specified initial capacity and the default load factor (0.75).
HashMap(int initialCapacity, float loadFactor)
          Constructs an empty HashMap with the specified initial capacity and load factor. 

So every time we exceed the number of element that can have in the data structure with respect to the load factor , JRE restructure the map according to the load factor .This restructuring is little bit expensive so its better to use this feature carefully .by doing this we can improve the performance of the HashMap.

What happen when load factor is 1?
This is the easiest way to avoid restructuring of the HashMap before it. If declare load factor as
1 the restructuring process only happens when number of elements are exceeding the capacity of the HashMap.

Note : Some may have a question about the wasted space when we use this type of declaration . As you can see if we use 1000 as a initial size we know that 250 memory spaces will be wasted but cost of wasting me space is so cheaper than wasting computational time so it is better to have this kind of declaration. But keep in mind this is not good for every situation and it is developer's responsibility to identify what will be used. As an example if we have no idea about how many data items are to be inserted to the data structure don't initialising when construct.

                That's about how load factor effect to the searching time . But in above I've mentioned that the load factor is only one factor that effect to the performance of the HashMap and HashSet . The initial size of the data structure is also effect to the performance and it will discussing on next article because it also little bit of lengthy topic and we need more knowledge about Hashing for it so it is advise to read more about a hashing technique called bucket hashing