Friday, 13 February 2015

Understanding how hashing (HashMap and HashSet) work in Java

Background

Hashing is a very important concept in computer programming and a very popular concept for interview questions. Two important data structures related to hashing are HashMap and HashSet which is exactly what we are going to look at in this post.

Overview

If you are from a computer science background you would know HashMap is a data structure which stores key value pairs where as a HashSet stores unique data. In HashMap we have kind of buckets and each data added to a HashMap falls into one of the buckets depending on the hash value of it. Also you must have heard that adding and retrieving objects in HashMap happen in time complexity O(1).

But still there are open end question like -
  • What happens when two objects added to HashMap have same hash (code) value ? - a situation typically known as collision.
  • If above is handled how get and put work in hashmap?.... and so on.
We will address them now.

Understanding how HashMap works

 You can visualize HashMap as follows-




So you have an Array and each array position is essentially a Linked List. As you know you don't have to specify size of the HashMap. It increases dynamically like ArrayList.  The main data structure is essentially an array.

    /**
     * The table, resized as necessary. Length MUST Always be a power of two.
     */
    transient Entry[] table;


When you create a HashMap you either choose to provide initial capacity or when you don't a default value is used.

    /**
     * The default initial capacity - MUST be a power of two.
     */
    static final int DEFAULT_INITIAL_CAPACITY = 16;


 When table is created it is created with either this initial default capacity or the capacity you provide in the constructor.

Next important thing is when should out table we resized to meet the dynamically changing data size of HashMap. Answer depends on a threshold that is determined by load factor.

    /**

     * The load factor used when none specified in constructor.

     */

    static final float DEFAULT_LOAD_FACTOR = 0.75f;


HashMap provides a constructor to initialize load factor as well. So when your data size equals

  • threshold = table capacity * load factor

then the HashMap table is resized. Constructors are as follows -

    /**
     * Constructs an empty <tt>HashMap</tt> with the specified initial
     * capacity and load factor.
     *
     * @param  initialCapacity the initial capacity
     * @param  loadFactor      the load factor
     * @throws IllegalArgumentException if the initial capacity is negative
     *         or the load factor is nonpositive
     */
    public HashMap(int initialCapacity, float loadFactor) {
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal initial capacity: " +
                                               initialCapacity);
        if (initialCapacity > MAXIMUM_CAPACITY)
            initialCapacity = MAXIMUM_CAPACITY;
        if (loadFactor <= 0 || Float.isNaN(loadFactor))
            throw new IllegalArgumentException("Illegal load factor: " +
                                               loadFactor);

        // Find a power of 2 >= initialCapacity
        int capacity = 1;
        while (capacity < initialCapacity)
            capacity <<= 1;

        this.loadFactor = loadFactor;
        threshold = (int)(capacity * loadFactor);
        table = new Entry[capacity];
        init();
    }

    /**
     * Constructs an empty <tt>HashMap</tt> with the specified initial
     * capacity and the default load factor (0.75).
     *
     * @param  initialCapacity the initial capacity.
     * @throws IllegalArgumentException if the initial capacity is negative.
     */
    public HashMap(int initialCapacity) {
        this(initialCapacity, DEFAULT_LOAD_FACTOR);
    }

    /**
     * Constructs an empty <tt>HashMap</tt> with the default initial capacity
     * (16) and the default load factor (0.75).
     */
    public HashMap() {
        this.loadFactor = DEFAULT_LOAD_FACTOR;
        threshold = (int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR);
        table = new Entry[DEFAULT_INITIAL_CAPACITY];
        init();
    }


How is data with keys generating same hash code stored in HashMap?

As mentioned earlier each index has reference to object of type Entry which is a Linked List. It has a next pointer. So if an entry is added to hash map it's hash code is computed which determines the index at which it should be put. If that index has an entry then new entry is added to the start of the linked list and existing linked list is appended to next of it.

    public V put(K key, V value) {
        if (key == null)
            return putForNullKey(value);
        int hash = hash(key.hashCode());
        int i = indexFor(hash, table.length);
        for (Entry<K,V> e = table[i]; e != null; e = e.next) {
            Object k;
            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
                V oldValue = e.value;
                e.value = value;
                e.recordAccess(this);
                return oldValue;
            }
        }

        modCount++;
        addEntry(hash, key, value, i);
        return null;
    }

    void addEntry(int hash, K key, V value, int bucketIndex) {
    Entry<K,V> e = table[bucketIndex];
        table[bucketIndex] = new Entry<K,V>(hash, key, value, e);
        if (size++ >= threshold)
            resize(2 * table.length);
    }


Also note how null is handled. Yes null is an acceptable key in HashMap.

So how is data retrieved if two keys generate same hash code?

Same hash code will make searched for both keys data land on same index in the table. From there the each Entry object is iterated over and it's key compared with the search key. Yes both key and value are stored in the Node/Entry object! On successful match corresponding value is returned.

    public V get(Object key) {
        if (key == null)
            return getForNullKey();
        int hash = hash(key.hashCode());
        for (Entry<K,V> e = table[indexFor(hash, table.length)];
             e != null;
             e = e.next) {
            Object k;
            if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
                return e.value;
        }
        return null;
    }

How data is stored in HashMap

 First of all the Node array size is always 2^N. Following method guarantees it -

static final int tableSizeFor(int cap) {

    int n = cap - 1;
    n |= n >>> 1;
    n |= n >>> 2;
    n |= n >>> 4;
    n |= n >>> 8;
    n |= n >>> 16;
    return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
}

So lets say you provide initial capacity as 5
cap = 5

n = cap - 1 =  4 = 0 1 0 0
n |= n >>> 1;    0 1 0 0 | 0 0 1 0 = 0 1 1 0 = 6
n |= n >>> 2;    0 0 1 1 | 0 1 1 0 = 0 1 1 1 = 7
n |= n >>> 4;    0 0 0 0 | 0 1 1 1 = 0 1 1 1 = 7
n |= n >>> 8;    0 0 0 0 | 0 1 1 1 = 0 1 1 1 = 7
n |= n >>> 16;   0 0 0 0 | 0 1 1 1 = 0 1 1 1 = 7
return n + 1     7 + 1 = 8 


So table size is 8 = 2^3

Now possible index values you can put your element in map are 0-7 since table size is 8. Now lets look at put method. It looks for bucket index as follows -

Node<K,V> p =  tab[i = (n - 1) & hash];

where n is the array size. So n = 8. It is same as saying

Node p = tab[i = hash % n];

So all we need to see now is how

hash % n == (n - 1) & hash

Lets again take an example. Lets say hash of a value is 10.

hash = 10
hash % n = 10 % 8 = 2
(n - 1) & hash = 7 & 10 = 0 1 1 1 & 1 0 1 0 = 0 0 1 0 = 2

So it's a optimized modulo operation with bitwise & operator.

A good hash function

A hash function is a method that computes hash of a key where data is stored. It should obviously return value between 0 - (n-1) for an array of length n used to store the data.

A good has function will have take minimum computation time will evenly distribute keys in the array. 
For array of size n and m elements inserted it's load factory would ideally be 

α = m/n

A hash function can be thought of two parts - 
  1. Hash code Map (Key -> Integer)
  2. Compression Map (Integer -> [0,N-1])
Simple hash function (Compression Map) for an array of size N would be

  • h(k) = k mod n where k is the key and n is the size of the array.

NOTE : In above function h(k) you need to take care that m is not  a power of 2. If you do you are only using last m bits of the number to compute hash in that case which is not a good method.

So choose m close to n and m should be prime.


Another compression map can be -

  • h(k) =lowerbound ( k A mod 1) where k is the key, m is the size of the array and A is a constant between 0 and 1 i.e 1<A<0
NOTE : For String avoid adding ascii values of characters as it is not a good function. Multiple words may result in same hash and map to same bucket resulting in higher collision. Use polynomial function instead. So if your integers of ascii chars are c0, c1, c2 use polynomial like -

C0 + C1(X) + C2(X^2)

String class in Java uses following has method -

    /**
     * Returns a hash code for this string. The hash code for a
     * <code>String</code> object is computed as
     * <blockquote><pre>
     * s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
     * </pre></blockquote>
     * using <code>int</code> arithmetic, where <code>s[i]</code> is the
     * <i>i</i>th character of the string, <code>n</code> is the length of
     * the string, and <code>^</code> indicates exponentiation.
     * (The hash value of the empty string is zero.)
     *
     * @return  a hash code value for this object.
     */
    public int hashCode() {
    int h = hash;
        int len = count;
    if (h == 0 && len > 0) {
        int off = offset;
        char val[] = value;

            for (int i = 0; i < len; i++) {
                h = 31*h + val[off++];
            }
            hash = h;
        }
        return h;
    } 



Other hashing techniques are
  1. Linear probing :

    if (table is full error)
    probe = h(k)
    while(table(probe) is not empty)
              probe = (probe + 1) mod m
    table[prob] = k
  2. double hashing :

    if (table is full error)
    probe = h1(k)
    offset = h2(k)
    while(table(probe) is not empty)
              probe = (probe + offset) mod m
    table[prob] = k

NOTE : In java if hashing is involved (lets say you are using HashMap or a HashSet) make sure you override equals() and hascode() method to suit your requirements.  As much as is reasonably practical, the hashCode() method defined by class Object does return distinct integers for distinct objects. (This is typically implemented by converting the internal address of the object into an integer)

HashMap changes in Java8

The performance has been improved by using balanced trees instead of linked lists under specific circumstances. It has only been implemented in the classes 
  1. java.util.HashMap, 
  2. java.util.LinkedHashMap and 
  3. java.util.concurrent.ConcurrentHashMap.
This will improve the worst case performance from O(n) to O(log n).

Lastly lets see HashSet.

Understanding HashSet

Well if you are still guessing the data structure of HashSet then following would be a surprise -

    private transient HashMap<E,Object> map;

    // Dummy value to associate with an Object in the backing Map
    private static final Object PRESENT = new Object();



Yup HashSet stores data as keys of HashMap with dummy value. Constructor is equivalent to that of HashMap -

    /**
     * Constructs a new, empty set; the backing <tt>HashMap</tt> instance has
     * default initial capacity (16) and load factor (0.75).
     */
    public HashSet() {
    map = new HashMap<E,Object>();
    } 



    public HashSet(int initialCapacity, float loadFactor) {
    map = new HashMap<E,Object>(initialCapacity, loadFactor);
    }



    public HashSet(int initialCapacity) {
    map = new HashMap<E,Object>(initialCapacity);
    }


Add and Remove methods are as follows -

    public boolean add(E e) {
    return map.put(e, PRESENT)==null;
    }



    public boolean remove(Object o) {
    return map.remove(o)==PRESENT;
    }

Understanding LinkedHashMap

LinkedHashMap as we know stores the insertion order. However it also extends HashMap so it respects O(1) time complexity as well for insertion. So how does it really work.

LinkedHashMap maintains another type on Entry which holds pointer to previous as well as next Entry Node.

    static class Entry<K,V> extends HashMap.Node<K,V> {
        Entry<K,V> before, after;
        Entry(int hash, K key, V value, Node<K,V> next) {
            super(hash, key, value, next);
        }
    }

LinkedHashMap also stores head and tail of this double linked list and thats how it maintains the insertion order. So even though put follows hashing storage and retrieval order is maintained using doubly linked list.

    /**
     * The head (eldest) of the doubly linked list.
     */
    transient LinkedHashMap.Entry<K,V> head;
    /**
     * The tail (youngest) of the doubly linked list.
     */
    transient LinkedHashMap.Entry<K,V> tail;

So whenever you add a new key, value pair following happens -

    Node<K,V> newNode(int hash, K key, V value, Node<K,V> e) {
        LinkedHashMap.Entry<K,V> p =
            new LinkedHashMap.Entry<K,V>(hash, key, value, e);
        linkNodeLast(p);
        return p;
    }
    // link at the end of list
    private void linkNodeLast(LinkedHashMap.Entry<K,V> p) {
        LinkedHashMap.Entry<K,V> last = tail;
        tail = p;
        if (last == null)
            head = p;
        else {
            p.before = last;
            last.after = p;
        }
    } 

When iterating it iterates from head to tail thereby providing same order as insertion.

NOTE : before and after pointers are in addition to the next pointer which is inherited from HashMap.Node class. So next points to next node having same hash (collision scenario) thereby preserving O(1) lookups. Before and After pointers guarantee insertion lookup order.

Understanding TreeMap

TreeMap as you already know stores the data in sorted order. If the data it stores implements Comparable interface then it stores data in that natural order or you can pass a custom comparator to the TreeMap and it will use that to sort and store the data.

TreeMap maintains a binary search tree structure. It has a root, value less than root go to left where as value greater than root go to right and it's balanced too (RBT - A red–black tree is a kind of self-balancing binary search tree).

    /**
     * The comparator used to maintain order in this tree map, or
     * null if it uses the natural ordering of its keys.
     *
     * @serial
     */
    private final Comparator<? super K> comparator;
    private transient Entry<K,V> root;

Simple code snippet would be -

        Entry<K,V> e = new Entry<>(key, value, parent);
        if (cmp < 0)
            parent.left = e;
        else
            parent.right = e;

where cmp is the comparison value got either from comparators compare() method or Comparables compareTo() method.

Related Links

Monday, 9 February 2015

Adapter and Facade Design Patterns in Java

Background

Some time back we saw Decorator design pattern which was the 1st Structural design pattern that we tried to understand. Adapter and Facade are two more design pattern that come under same category - Structural Design pattern.

Adapter Design Pattern

Adapter pattern converts one interface to another interface that is expected by the target or client system. It simply make interfaces compatible so that integration is possible. To visualize see following diagram


Target or client expects an interface where as interface that is going to use it provides different interface and none of them can be modified. In such cases Adapter proves to be beneficial.

Lets take an example -

Lets say you have designed a program that computes cost of a list of items supplied to it. In your computeCost() method you expect that customer would provide Iterator instance. You write code something like below -

import java.util.Iterator;


public class CostComputer {
    
    public static int computeCost(Iterator<Product> iterator)
    {
        int cost = 0;
        while(iterator.hasNext())
        {
            cost = cost + iterator.next().getCost();
        }
        return cost;
    }
    
}


Also you have exposed a Product interface. Those who want to compute cost should have models extending this Product interface implement it's getCost() method and then can pass the iterator of it to above utility method.

public interface Product {
    int getCost();
}



Now here's something you did not expect.  You get a Toy manufacturing company as your client and their code is something like -

public class Toy implements Product {

    int cost;
    
    public Toy(int cost)
    {
        this.cost = cost;
    }
    
    @Override
    public int getCost() {
        return cost;
    }

}


and

import java.util.Enumeration;
import java.util.Random;
import java.util.Vector;


public class ToysCreator {
    
    int count;
    
    public ToysCreator(int count)
    {
        this.count = count;
    }
    
    public Enumeration createToys()
    {
        Vector toys = new Vector<>();
        for(int i=0; i<count ;i++)
        {
            toys.add(new Toy(new Random().nextInt(10)));
        }
        return toys.elements();
    }

}


and then they tried to use your code as follows -

public class ToysCostComputer {
    
    public static void main(String args[])
    {
        System.out.println(CostComputer.computeCost(new ToysCreator(6).createToys())); // this will fail
    }

}


and viola -

Exception in thread "main" java.lang.Error: Unresolved compilation problem:
    The method computeCost(Iterator<Product>) in the type CostComputer is not applicable for the arguments (Enumeration)

    at ToysCostComputer.main(ToysCostComputer.java:6)

Program crashed. Your code expected a Iterator but customer code returns Enumeration. Now you or your customer have to build Adapter to support Enumeration.

It goes as follows -

import java.util.Enumeration;
import java.util.Iterator;


public class EnumToIteratorAdapter implements Iterator<Product> {

    Enumeration<Product> enumeration;
    
    public EnumToIteratorAdapter(Enumeration<Product> enumeration)
    {
        this.enumeration = enumeration;
    }
    
    @Override
    public boolean hasNext() {
        return enumeration.hasMoreElements();
    }

    @Override
    public Product next() {
        return enumeration.nextElement();
    }

    @Override
    public void remove() {
        throw new UnsupportedOperationException();
        
    }

}


and now client can use our code with the help of Adapter

import java.util.Iterator;


public class ToysCostComputer {
    
    public static void main(String args[])
    {
        Iterator toysIterator = new EnumToIteratorAdapter(new ToysCreator(6).createToys());
        System.out.println(CostComputer.computeCost(toysIterator));
    }

}


and the output is - 27. Some random number but you get the point.

Class Diagram for our above demo is as follows -



Generic Class diagram for Adapter Pattern is as follows -



That was Adapter Pattern. Now lets come to facade pattern.

so in facade pattern Adapter implements target and has an instance of Adaptee. So whenever methods of target are called we call suitable methods of adaptee.

Facade Pattern.

Facade Pattern is kind of an overlay. It provides a unified interface to set of interfaces in the sub system. Note that we cannot say it encapsulates methods of sub system classes as methods of sub system classes are still available for direct use. Facade pattern just simplifies it by abstraction.

There is no fixed generic class diagram as such but it will look like -


Lets say you have multiple modules for handling program bugs. May be
  1. class BugCreator that creates various types of bugs - UI, functional, localization etc. 
    • Methods : createBug(String bugType) etc
  2. class BugsReplicator that tries replicates the bug as per the description of filed bug.
    • Methods :  replicateBug(Bug newBug) etc
  3. class BugsSolver that finds the fix and checks in the code.
    • Methods : fixBug(Bug newBug) etc
  4. class BugsDeployer that deploys the fix to dev or qa environments.
    • Methods : deployFix(CodeFix fix) etc
  5. class BugsTester that tests out the fix
    • Methods : testFix(Bug bug) etc
Now lets say your customer uses these classes or subsystems to handle their code bugs. They will have to call each method and do handling on their own. Instead you can provide them with a simplified facade.

public boolean resolveBug(String desc, String bugType)
{
      Bug newBug =  new BugCreator().createBug(bugType);
      boolean replicated = new BugsReplicator .replicateBug(newBug);
      if(replicated)
      {
          CodeFix fix = new BugsSolver().fixBug(newBug);
          new BugsDeployer().deployFix(fix);
          if(new BugsTester.testFix(Bug bug))
          {
              return true;
          }
          else
          {
              return false;
          }
      }
      else
      {
          return false;
      }
}


Now this is just an example that I am giving to help you understand how Facade pattern simplifies subsystem complexity. 


Notes

  • Facade does not encapsulate subsystem classes. It simply provides simplified interface to complex subsystem classes. Subsystem classes are still accessible for direct use.

Summary

  • Decorator pattern does not alter any interface. It simply adds responsibility.
  • Adapter pattern Converts one interface (Adaptee) to another (Target) for compatibility.
  • Facade pattern simplifies interface for complex subsystem subclasses.

Related Links

Saturday, 7 February 2015

String processing using Matcher, Pattern and Regex in Java

Background

Using regex or simply regular expressions have been very important part of String processing. We will explore it is this post.


Before you get to Java code lets take a looks at Regex symbols - 

Regex Symbols

Common Regex Symbols : 

Common Regex Meta Symbols : 


Common Regex Quantifier Symbols : 

Now lets head on to Java Code....

Using java.util.regex.Pattern and java.util.regex.Matcher classes

Lets use these classes to demonstrate regex.

    public static void main(String args[])
    {
        String str = "Hi there! My name is John. How can I help you?";
        Pattern p = Pattern.compile("[.!?]");
        Matcher matcher = p.matcher(str);
        int count = 0;
        while(matcher.find()) {
            count++;
        }
        System.out.println("Count : " + count);

    }

and the output is - 3. Lets see what we did here. We have a String - "Hi there! My name is John. How can I help you?"  and we are interested in finding number of times symbol '.', '!' or '?' appears in the String. So we provided the regex "[.!?]". 

Did not quite get the regex part? Go back to previous section - Regex symbols. Notice in Common Regex symbols image [xyz] represent x or y or z. We are simply incrementing the counter if we find such a regex meaning '.', '!' or '?' '.

Lets head on to something more interesting. How many time have you used String classes split() method? Did you realize that it is infact a regex that split method takes. We split words from line as follows -

    public static void main(String args[])
    {
        String str = "Hello all. Welcome to Open Source For Geeks!";
        String[] tokens = str.split(" ");
        for(String token : tokens)
        {
            System.out.println(token);
        }

    }


and you get output as -

Hello
all.
Welcome
to
Open
Source
For
Geeks!


as expected.  If you see the split method code it internally used java.util.regex.Pattern to compile you regex and use it to split the String -

    public String[] split(String regex, int limit) {
    return Pattern.compile(regex).split(this, limit);
    }


Now lets do the same thing as split using Patter and Matcher.

    public static void main(String args[])
    {
        String str = "Hello all. Welcome to Open Source For Geeks!";
        Pattern pattern= Pattern.compile("\\w+");
        Matcher matcher = pattern.matcher(str);
        while(matcher.find()) {
            System.out.println(matcher.group());
        }

    }


and the output is -

Hello
all
Welcome
to
Open
Source
For
Geeks


Noticed any difference? '.'(dot) and '!'(exclamation) are not present. Well that is expected. See Regex symbols again. We used "\\w+"  which means match one or more word character and dot and exclamation aren't one of them.

Note : Space is also not a word character. Else we would have got whole String as matched pattern (leaving dot and exclamation mark aside). Digits are also part of word characters i.e \\w+ .

 So lets slightly modify our code to get the same output.

    public static void main(String args[])
    {
        String str = "Hello all. Welcome to Open Source For Geeks!";
        Pattern pattern= Pattern.compile("\\w+\\.*!*");
        Matcher matcher = pattern.matcher(str);
        while(matcher.find()) {
            System.out.println(matcher.group());
        }

    }


and the output is -

Hello
all.
Welcome
to
Open
Source
For
Geeks!


Ok that's the same. What did we do here? Notice the regex again. This time it is - "\\w+\\.*!*". We are saying get me sequence that matches [(one or more word characters) then (zero or more dot symbols) then (zero or more exclamation symbols)].

Note :  Dot is a regex symbol and hence you need to escape (like we did \\. ) it if you want to use it for searching dot pattern. Exclamation on the other hand was not so we could directly use it.


Another Example


Lets  do something practical now. Lets say you have following data (maybe in a file or just an array) -

data1=${key1}
data2=${key2}
data3=${key3}

and you have to replace the placeholder with the actual value whose mapping you have (again maybe in a different file).

key1 -> ActualKey1
key2 -> ActualKey2
key3 -> ActualKey3

and finally you want output like -

data1=ActualKey1
data2=ActualKey2
data3=ActualKey3

Lets write code to achieve this using regex.

    public static void main(String args[])

    {

        String[] replacableData = new String[]{"data1=${key1}","data2=${key2}","data3=${key3}"};

        Map<String, String> keyMappings = new HashMap<String, String>();

        keyMappings.put("key1", "ActualKey1");

        keyMappings.put("key2", "ActualKey2");

        keyMappings.put("key3", "ActualKey3");

        Pattern pattern= Pattern.compile("(\\w+=)(\\$\\{)(\\w+)(\\})");

        for(String str : replacableData) {

            Matcher matcher = pattern.matcher(str);

            String key = matcher.replaceAll("$3");

            System.out.println("Key : " + key);

            String newStr = matcher.replaceAll("$1"+ keyMappings.get(key));

            System.out.println("After Replacement : " + newStr);

        }

    }


and the output is -

Key : key1
After Replacement : data1=ActualKey1
Key : key2
After Replacement : data2=ActualKey2
Key : key3
After Replacement : data3=ActualKey3


Another important concept to note here is the groups in the rgex that you can refer later with $groupIndex.

In our regex - "(\\w+=)(\\$\\{)(\\w+)(\\})"

group1 -> (\\w+=)
group2 -> (\\$\\{)
group3 -> (\\w+)
group4 -> (\\})
  Also replaceAll() replaces the entire original String with whatever group combinations you provide. For example matcher.replaceAll("$1$2$3$4") will give you back the same String.

Note : replaceAll() method return a new String. original String is not changed.

Note :  Even used replace() and replaceAll() method of String class?  Both of them replace all occurences with the String you desire. Only difference is replaceAll() uses a regex where as replace() uses simple CharSequence.

Friday, 6 February 2015

Difference between Dalvik and ART runtimes in Android

Background

If you own an Andorid device with Kitkat you would already know this. You have an option of choosing between the runtimes - 
  • Dalvik
  • ART

What is runtime you ask? -  Think of it as a library that takes care of converting the code that you write in a high level language like Java to machine code that the processor/cpu will understand. Android uses virtual machine as it's runtime (like JVM) which makes it "write once run everywhere".


From Android L (5.0) ART has been made as the default runtime (ART has completely replaced Dalvik).

For my device running Kitakat it looks like the following -




The goal of this post is to understand these runtimes so that you can choose the appropriate one (in Android kitkat). Before proceeding to the details I would recommend read more about JIT (Just in time) compilation. You can see the JIT section in my following post -


 History

Lets step back a little and see how did we reached to ART. We all know Dalvik was used as the virtual machine. In it's simple form consider Dalvik as JVM optimized for mobile platforms. Later from Android 2.2 (Froyo) JIT compiler was launched (which Dalvik used) to further optimize and improve applications performance. JIT allows code to be directly compiled to native code (unlike interpreting it every time) and use the same thereafter. JIT did these only for so called "identified hotspots" (typically code snippets getting executed very frequently). So still major code was interpreted and need was felt to further optimize and improve performance of Android application and hence from Android 4.4 (kitkat) ART was introduced as a runtime and from Android 5.0 (Lollipop) it has completely replaced Dalvik. 

Android Architecture with ART looks like -


So Dalvik used JIT(Just in time) compilation where as ART uses AOT (Ahead of time) compilation. Lets see what that is.

 AOT (Ahead of time) Compilation and ART

We all know android apps come in .apk format. You essentially write you code in Java (.java classes) which are bundled in apk files. While application gets bundles your java classes are converted to bytecodes (.dex) files. This is common for both Dalvik as well as ART. Difference is what comes next.

In JIT/Dalvik every time an application is launched byte code is interpreted line by line. If a routine or function is identified as hotspot it is directly compiled to native code by JIT with optimization. This leads to time and memory footprint overhead as this is done on the fly when application is running. The JIT compiled code is then run directly everytime thereafter (no interpretation needed) which increases the performance.

In AOT/ART when application (.apk) file is installed entire byte code is converted to machine code and stored in the persistent storage. As this is on installation this happens only once. Every time the application is launched this machine code is directly executed. No need of interpreter. yes it takes more storage space as compiled native code is stored in the storage but takes less CPU and less RAM (memory footprint).

As per Wiki,

To maintain backward compatibility, ART uses the same input bytecode as Dalvik, supplied through standard .dex files as part of APK files, while the .odex files are replaced with Executable and Linkable Format (ELF) executables. Once an application is compiled by using ART's on-device dex2oat utility, it is run solely from the compiled ELF executable; this approach eliminates various overheads involved with JIT compilation, but it requires additional time for compilation when an application is installed, and applications take up slightly larger amounts of space to store the compiled code


Following diagram should clear everything I just explained above - 


Benefits of ART

  • Reduces startup time of applications as native code is directly executed.
  • Improves battery performance as power utilized to interprete byte codes line by line is saved.
  • As JIT is not in the picture no on the fly compilation and native code storage. This significantly reduces memory footprint (less RAM is required for application to run).

Drawbacks of ART

  • As dex bytecodes are converted to native machine code on installation itself, installation takes more time.
  • As the native machine code generated on installation is stored in internal storage, more internal storage is required.

Related Links

Wednesday, 4 February 2015

The Decorator pattern design pattern

Background

This pattern employes a very important OO design principle -
  • Classes should be open for extension but closed for modification.
This design pattern allows new functionality to be added to an existing Object without modifying it's structure.  Also this is the 1st structural design pattern that we are taking a look at. If you remember there are 3 types of design patterns -

  1. Creational
  2. Structural
  3. Behavioral

Lets take an example to understand this better. Lets say you have opened a Pizza shop and you offer various types of Pizzas.



You then created classes for each type of Pizza. Now that you are very well versed with following design principle -
  • Code for interface and not implementation
you would probably create an interface Pizza and then make concrete class like PaneerPizza, ChickenPizza by implementing Pizza interface. But now lets say your business grows and you offer various types of toppings like extra cheese or mushrooms or spicy chicken or corn. For this you will have to now either create new concrete Pizzas or alter existing code. But this is not practical as every time you decide to offer or remove a new topping you code will change (Think of each Pizza having a getCost() method which will differ with toppings). This is where Decorator pattern comes to the rescue.


Generic Class Diagram



Source : Wiki


To the Code....

Lets first create an interface - Pizza

public interface Pizza {
    int getCost();
}

Now lets create concrete classes for Pizza - 

public class PaneerPizza implements Pizza {

    @Override
    public int getCost() {
        return 3;
    }

}

and

public class ChickenPizza implements Pizza {

    @Override
    public int getCost() {
        return 5;
    }

}

And now lets create decorator class. Remember decorator class will implement Component and will also have an instance of Component in it. Also the operation method which is this case is getCost() will be abstract.

public abstract class PizzaDecorator implements Pizza {

    

    Pizza pizza;



    public abstract int getCost();



}

and now lets create concrete classes for Toppings which will extend PizzaDecorato.

public class MushroomToppings extends PizzaDecorator {

    public MushroomToppings(Pizza pizza) {
        this.pizza = pizza;
    }
    
    @Override
    public int getCost() {
        return 2 + pizza.getCost();
    }

}

and

public class CornTopping extends PizzaDecorator {

    public CornTopping(Pizza pizza) {
        this.pizza = pizza;
    }
    
    @Override
    public int getCost() {
        return 1 + pizza.getCost();
    }

}

and  that's all with the model classes. Now lets simulate it and see,

/**
 * @author athakur
 */
public class PizzaSimulation {
    
    public static void main(String args[])
    {
        Pizza pizza = new ChickenPizza();
        System.out.println("Pizza cost : " + pizza.getCost());
        
        Pizza pizzaWithCornToppings = new CornTopping(pizza);
        System.out.println("Pizza cost : " + pizzaWithCornToppings.getCost());
        
        Pizza pizzaWithCornAndMushroomToppings = new MushroomToppings(pizzaWithCornToppings);
        System.out.println("Pizza cost : " + pizzaWithCornAndMushroomToppings.getCost());
        
    }
}



And the output is -

Pizza cost : 5
Pizza cost : 6
Pizza cost : 8


Now go back to each Pizza and Topping class and verify the output. It's pretty straight forward. See how we could dynamically add toppings and compute total cost without actually modifying the original class? That the power of Adapter patter.


NOTE : In decorator pattern decorator implements the component and also composes the component.
NOTE : In adapter pattern adapter implements the target and composes the adaptee.

Class Diagram for Above Pizza Store Code

Related Links


Summary

  • Decorator pattern does not alter any interface. It simply adds responsibility.
  • Adapter pattern Converts one interface (Adaptee) to another (Target) for compatibility.
  • Facade pattern simplifies interface for complex subsystem subclasses.
t> UA-39527780-1 back to top