Tuesday, January 31, 2017

6-Collections operational APIs in common

Sorting

  • Already sorted Collections are as below. 
    • TreeSet
    • TreeMap
However for the rest, a comparator needs to be implemented in 3 following ways:
  • sort() method for sorting List:
    • List l = new ArrayList(Arrays.asList(3, 5, 4, 2, 3, 2, 1, 3));
    • Collections.sort(l); //increasing order
    • System.out.println("Increasing order:"+l);
    • O/p: Increasing order: [1, 2, 2, 3, 3, 3, 4, 5]
    • .
    • However, The element’s class must implement Comparable interface. This is mandatory since this version of sort() uses element’s compareTo() method to compare them. Otherwise a ClassCastException will be thrown.


  • custom Sort method for sorting List:Steps to create custom Comparator are below:
    • create a custom comparator class that implements Comparator interface, and implement its compare() method as below:
      • class IntegerComparator implements Comparator {
      •     public int compare(Object o1, Object o2) {
      •       return (Integer)o2 - (Integer)o1;
      •     }
      • }
    • Note that the Object that is compared(Integer in this case) needs to implement Comparable interface in order to be use a comparator(IntegerComparator  in this case) for comparison.
      • This customComparator(IntegerComparator) then used as in below code:
        • Collections.sort(l, new IntegerComparator());//decreasing order
        • System.out.println("Decreasing order\n"+l);
    • Using unnamed Comparator class(within sort() call)
      • Collections.sort(l, new Comparator() {
              • public int compare(Object o1, Object o2) {
              • return (Integer)o2 - (Integer)o1;
              • }}
            • ); //decreasing order
    _______________________________________________________________________


    Shuffling

    • The opposite of sort is shuffle which arranges list elements arbitrarily.
    • Two versions of shuffle() are :
      1. One operates on a List using a default source of randomness.
        • Collections.shuffle(l);
      2. Another requires a Random object to be specified explicitly.
        • Collections.shuffle(l, new Random());

    _______________________________________________________________________

    Manipulation

    • Reversing Collections.reverse(list);
    • Swapping : swaps elements of two specified positions of a specified list
      • Collections.swap(list,2, 4);
    • Copying : Copy all the elements on lists1 into list2
      • Collections.copy(list1, list2);
    • Filling : fill all elements of list1 with "0", wrt to example below
      • Collections.fill(list,0);
    • Adding: Collections.addAll(l1, -1, -2, -3);//Adds three integers to the list l1.
    _______________________________________________________________________

    Search

    • binarySearch(): It is common to use sort() method to sort the List before a call to binarySearch().
      • Collections.sort(list); //list=[1, 2, 2, 3, 3, 3, 4, 5]
      • int in = Collections.binarySearch(l, 4); //in = 6
      • in = Collections.binarySearch(list, 2); //in = 1
      • in = Collections.binarySearch(list, 3); //in = 3
    • For unsuccessful search, it returns a value (-(insertion point) - 1),
      • in = Collections.binarySearch(list, 0); //in = -1
    _______________________________________________________________________

    min()/max()

    • int min = (int)Collections.min(list); //min = 0
    • int max = (int)Collections.max(list); //max = 6
    _______________________________________________________________________

    frequency()
    • int fre = Collections.frequency(list,2); //fre = 2
    • fre = Collections.frequency(list,3); //fre = 3


    _______________________________________________________________________

    Monday, January 30, 2017

    5-Collections


    -------------------------------------------------------------------------------------------------------------------------
    Set : (HashSet, LinkedHashSet, TreeSet)

    3 general implementations of Set:
    • To retrieve elements from the Set, we can either use Iterator or for-each loop.
    • Random access to an element in a set not allowed.


    HASHSET(unsortedSet):
    • does not guarantee any insertion and iteration orders.
    • Is a hash-based implementation and internally it
    • uses HashMap which is one of the Map implementations.
    • (Applies to all other sub Sets-----------------------------------------------------)
    • Different ways of implementing::
      • Set empty = new HashSet(); //{}
      • Set even = new HashSet(Arrays.asList(0,2,4)); //{0, 2, 4} -- (*)
      • Set copy = new HashSet(even); //create from existing Set
      • Set blank = new HashSet(8); //initial capacity 8
      • Set nullSet = new HashSet(8, 1); //initial capacity 8, load factor 1
    • Add an element : even.add(6); //{0, 2, 4, 6}----(*)
    • Add all of element of S2 to S3: s3.addAll(s2); //s3 = {1, 2, 3, 4, 5}
    • Remove an element: even.remove(4); //{0, 2, 6, 8}
    • Remove All: even.clear(); //{}
    • Remove elements common in S2 AND S3 from S3: s3.removeAll(s2); //s3 = {1}
    • Existence of an element: boolean c1 = even.contains(6); //c1 = true
    • Check for Emptinessboolean e1 = even.isEmpty(); (or) if(blank.size() == 0) ;
    • To Array from elements : Object[] a = even.toArray();
    • Retain only s2 elements in s3: s3.retainAll(s2); //s3 = {2, 3}
    • Synchronize a Hashset using Collections: Set syncSet = Collections.synchronizedSet(new HashSet());
    • (Applies to all other sub Sets-----------------------------------------------------)

    LinkedHASHSET(unsortedSet):
    • Unlike Hashset, LinkedHashset is ordered.
    • It is an extension to HashSet and uses linked list and hash table internally.
    • As it maintains a linked list, it exhibits slightly slower performance than HashSet.
    • SAME operation APIs as Hashset
    • Synchronized same as Hashset: Set syncSet = Collections.synchronizedSet(new LinkedHashSet());
    TreeSet(sortedSet):
    • does natural ordering on its elements. Also accepts a custom comparator for custom ordering.
    • log(n) time cost for the basic operations such as add(), remove() and contains().
    • SAME operation APIs as Hashset. Note that adding occurs in a sorted order. So, if u add an element, it is placed at the sorted location.
      • let, SortedSet ss = new TreeSet(Arrays.asList(2,3,5)); //{2,3,5}
      • ss.add(1); //ss = {1, 2, 3, 5}
      • ss.add(4); //ss = {1, 2, 3, 4, 5}
    • Synchronized same as Hashset: Set syncSet = Collections.synchronizedSet(new TreeSet(Arrays.asList(2,3,5)));
    • Additional Methods for a TreeSet are:
      • Object fe = ss.first(); //fe = 1
      • Object le = ss.last(); //le = 5
      • SortedSet s1 = ss.headSet(3); //s1 = {1, 2}-- returns all elements < "3"
      • SortedSet s2 = ss.tailSet(3); //s2 = {3, 4, 5}--returns elements >="3"
      • SortedSet s3 = ss.subSet(2, 5); //s3 = {2, 3, 4}-- >=2 and <5
    ***

    Iterator:are APIs used to Iterate over SET implementations.we can either use Iterator or for-each loop to retrieve elements from a set.
    • hasNext() – Returns true if there are more elements in the collection; false otherwise
    • next() – Returns the next element
    • remove() – Deletes the last element returned from the collection
    Example of Iterating over Set using Iterator API:

    Iterator i = setImplementatiomVariable.iterator();
    while(i.hasNext()) System.out.print(i.next()+" ");

    (or)


    for(Iterator i = even.iterator();i.hasNext();)
    System.out.print(i.next()+" ");


    -------------------------------------------------------------------------------------------------------------------------
    List : (ArrayList, LinkedList, Vector)
    3 general implementations of List:

    • Unlike sets, lists are ordered collection and
    • allow duplicate elements.
    • In addition to normal Iterator, List interface provides a special iterator, called a ListIterator, that unlike Iterator allows insertion and replacement of elements. Allows bidirectional traversal of the list,element.
      • ListIterator li = l.listIterator(); //sets cursor at the begining
      • while(li.hasNext()) System.out.print(li.next()+" ");
      • O/P: 2->3->4->2

      • while(li.hasPrevious()) System.out.print(li.previous()+" ");
      • O/P: 2->4->3->2

    ArrayList:
    • As elements are added and removed, its capacity grows or shrinks automatically.
    • a high capacity may be specified using ensureCapacity(), to reduce incremental reallocation.
      • List el = new ArrayList(); //empty list
      • List l = new ArrayList(Arrays.asList(2,3)); //l = 2->3
      • List l1 = new ArrayList(10); //empty, initial capacity 10
    • Add elements using the index(if given, else append at the end)
      • l.add(2); //append, l = 2->3->2
      • l.add(2, 4); //insert 4 at index 2, l = 2->3->4->2
    • Update :
      • l.set(0, 4); //l = 4->2
    • Remove:
      • l.remove(2); //remove element from index 2, l = 2->3->2
      • l.remove(new Integer(3)); //remove the element 2, l = 2->2
    • Remove All: l.clear(); //l=
    • retrieve Object obj = l.get(1); //obj = 3
    • retrieve sublistList sl = l.subList(1, 3); //sl = 3->4
    • retrieve based on index:
      • int first = l.indexOf(2); //first = 0;
      • int last = l.lastIndexOf(2); //last = 1;
    • Check for Emptinessboolean e1 = l.isEmpty(); (or) if(l.size() == 0) ;
    • Synchronize a ArrayList using Collections: Set syncSet = Collections.synchronizedSet(new ArrayList());
    LinkedList(implements two collection interfaces, List and Deque):
    • SAME operation APIs as ArrayList.
    • Synchronize a LinkedList using Collections: Set syncSet = Collections.synchronizedSet(new LinkedList());
    -------------------------------------------------------------------------------------------------------------------------
    Queue: (Queue,Stack) -casting LinkedList/ PriorityQueue
    • Like List, it also represents an ordered collection of elements
    • generally do not accept null elements.
    • Queues implementations can order elements in 
      • FIFO (queue), 
      • LIFO (stack)
      • and priority basis.
    • provides two forms of methods for inserting, deleting and inspecting elements.
      • One form throws an exception if the operation fails. 
      • The other form returns a special value such as null or false, depending on the operation.



    casting LinkedList to Queue(implements two collection interfaces, List and Deque):
    • By default, queues are FIFO ordered-Queue
    • ways to implement queues by casting to LinkedList:
      • Queue empty = new LinkedList(); //empty queue
      • Queue q = new LinkedList(Arrays.asList(1,3)); //q = 1->3
    • Add:
      • q.add(5); //q = 1->3->5
      • q.offer(7); //q =  1->3->5->7
    • Delete:
      • q.remove(); //q = 3->5->7.. and returns 1(1st addede element)
      • q.poll(); //q = 5->7
    • Retrieve element at the head of the queue(without deleting):
      • Object e = q.element(); //e = 5
      • Object e1 = q.peek(); //e1 = 5
    • a LIFO ordered queue (i.e. stack) may be created as follows:
      • Queue lifo = Collections.asLifoQueue(new LinkedList());
      • add and remove perform addition and removal in the opposite direction compared to queue.
    casting PriorityQueue to Queue:
    • least(element with lowest value) element always sits at the top (head). Refer add()
    • Element’s class must implement Comparable interface which has comparison method compareTo().
    • ways to implement queues by casting to PriorityQueue:
      • Queue empty = new PriorityQueue(); //empty queue
      • Queue q = new PriorityQueue(Arrays.asList(7,4,5)); //q = 7->4->5
    • Add:
      • q.add(3); //3 is at head
      • q.add(6); //3 is still at head
      • q.offer(2); //2 is at head
    • Delete/Retrieve(same as casting to LinkedList): 
    • Delete:
      • q.remove(); 
      • q.poll();
    • Retrieve element at the head of the queue(without deleting):
      • Object e = q.element(); 
      • Object e1 = q.peek(); 
    -------------------------------------------------------------------------------------------------------------------------

    MAP: 
    (HashMap, HashTable, TreeMap(implements SortedMap which inturn implements Map))

    general implementations of MAP:

    • This interface models a set of key-value pairs.
    • The keys are unique and each key corresponds to one value.
    • Common APIS for all MAP implementations:
      • put() 
      • get()
      • remove("keyStr") - remove entry from map corresponsding to key value "keyStr"
      • clear() -removes all the entries from the map.
      • containsKey()
      • containsValue()
      • size()
      • isEmpty()
      • keySet() - returns a Set of all keys
      • values() - returns a Collection of all values in the map
      • entrySet(); - returns a set of Map.Entry objects each of which consists of a key and a value


    HashMap:
    • does not also ensure any ordering.
    • Map syncMap = Collections.synchronizedMap(new HashMap());
      • Alternatively, we may use java.concurrent.ConcurrentHashMap which is thread-safe version of HashMap. 
      • ConcurrentHashMap also used instead of HashMap to obtain FailSafe condition(Failfast - exception thrown of new element added during iteration of the Map))
    • offers constant time [i.e. O(1)]
    • Each HashMap object is characterized by two parameters: capacity and load factor. The capacity is the number of buckets in the hash table. The load factor controls when to rebuild the internal data structures.
    • Ways to implement HashMap:
      • Map m = new HashMap(); //empty map
      • Map m1 = new HashMap(8); //initial capacity 8
      • Map m2 = new HashMap(6, 1); //initial capacity 6, load factor 1
      • Map m3 = new HashMap(m); //m3 = m
    LinkedHashMap:
    • LinkedHashMap is ordered. It extends HashMap and uses a doubly linked list and hashtable internally.
    • All others applies same as HashMap.

    TreeMap(Implements SortedMap):
    • entries are ordered wrt key in natural ordering (or) Comparator specified during map creation
    • log2(n) time for get(), put(), remove() and containsKey() methods
    • Ways to implement TreeMap:
      • SortedMap sm = new TreeMap(); //empty map
      • SortedMap sm1 = new TreeMap(sm); //create from existig sorted map
    • get an unsorted Map implemenetaion sorted as below:
      • Map m = new HashMap();
      • m.put("uttam","uttam1"); //add some entries
      • m.put("bibhas","bibhas1");
      • m.put("parama","parama1");
      • m.put("samiran","samiran1");
      • sm = new TreeMap(m); //get sorted from unsorted one

      • This results in the following sorted order:
      • bibhas->bibhas1
      • parama->parama1
      • samiran->samiran1
      • uttam->uttam1
    • The two special keys—the lowest (first) and the highest (last) keys are obtained as follows:
      • String k1 = (String)sm.firstKey(); //k1 = "bibhas"
      • String k2 = (String)sm.lastKey(); //k2 = "uttam"
    • the head and tail views may be retrieved as:
      • SortedMap hm = sm.headMap("samiran"); //hm = {bibhas=bibhas1, parama=parama1}
      • SortedMap tm = sm.tailMap("samiran"); //tm = {samiran=samiran1, uttam=uttam1}
    -------------------------------------------------------------------------------------------------------------------------

    Reference of below screenshot:



    Sunday, January 29, 2017

    4-Exception Handling

    reference: "Advanced Java Programming" by Utham.K.Roy

    Every Exception extends another. The Root of all Exceptions being Throwable class.
    • Checked Exception: Exceptions that must be caught/declared-to-be-thrown explicitly.
    • Unchecked/also called runtime Exception: Exceptions that needn't be caught/declared-to-be-thrown explicitly.
    Error : can neither be anticipated not be recovered from. Ex. OutOfMemory, StackOverflow, ClassFormat, NoClassFound, etc

    Exceptions: Can be caught and handled.

    ----------------------------------------------------------------------------------------------------

    printStackTrace():method prints a stack trace of the current exception on the standard error.
    ----------------------------------------------------------------------------------------------------

    Try-Catch blocks :

    There can be multiple catches blocks for a single try block. If all exceptions are subclasses of a certain Exception-Type, then just the at exception can be caught using the catch block as all the subclass exception will eventually be caught with just one catch block of the parent Exception.

    However, if multiple catch blocks with different parents, then , instead of using multiple blocks, we could still use a single Catch block using the pipeline character(since JAVA SE7) as below example:
    catch(ArrayIndexOutOfBoundsException|ArithmeticException e)
    {
        System.out.println(e);
    }

    • catch blocks must be arranged from most specific to most general. So, the following catch blocks are valid:
      • catch(ArrayIndexOutOfBoundsException e) {} catch(Exception e) {}
    • Here, the first catch block only catches ArrayIndexOutOfBoundsException whereas second one catches everything else.
    ----------------------------------------------------------------------------------------------------
    'throw' keyword :
    class Throw Test
    {
         public static void main(String[] args) {
             try { throw new Exception("test");
                   }
             catch(Exception e) { System.out.println(e); }
         }
    }
    • Only objects that are instances of Throwable class (or one of its subclasses) may be thrown by the throw statement.
    • Similarly, only this class or one of its subclasses can be the argument type in a catch clause.


    'throws' keyword :
    • This keyword is declared in the definition of a method with a certain exception 'A', to indicate that this method would possibly throw an exception of type 'A'.
    • multiple Exceptions can be declared with throws keyword separated by commas.
    • The method could declare with throws keyword and decide to not throw also.
    example:
    class ReThrowTest {
         void f() throws Exception
         {
              try {
                   throw new Exception();
              }
              catch(Exception e) {
                   System.out.println("Handled paritally in f()");
                   throw e;
              }
         }

         void g()
         {
              try {
                   f();
              }
              catch(Exception e) {
                   System.out.println("Handled completely in g()");
              }
         }

         public static void main(String[] args) { 
              new ReThrowTest().g();
         }
    }

    However, the exception used with throws keyword should match the exception that is being thrown using the throw keyword.

    ----------------------------------------------------------------------------------------------------
    'finally' block:

    • Always executed if exists, irrespective of exception catch or not.
    • Only one finally block.
    • if catch blocks exists, then finally follows only after the catch block/blocks
    • if no catch block, finally block can follow immediately after try
    • no Finally block after try catch or try is also legal

    ----------------------------------------------------------------------------------------------------
    'try', with resources, the resources need to implement java.lang.Autocloseable interface:(which has a single method close()):
    Example :
    class TryWithResourcesTest1 {
    public static void main(String args[]) throws Exception {
    try {
           try (MyResource mr = new MyResource()) {
                  System.out.println("Throwing from try block");
                  throw new Exception("try block");   ---(*)
           }
    }
    catch(Exception e) {
           System.out.println(e);
           Throwable[] t = e.getSuppressed();
           System.out.println("Suppressed exception...");
           for(int i=0;i<t.length;i++)
                  System.out.println(t[i]);
           }
    }
    }

    class MyResource implements AutoCloseable {
           public void close() throws Exception {
                  System.out.println("Throwing from close()");
                  throw new Exception("close()");
           }
    }


    OUTPUT:
    Throwing from try block
    Throwing from close()
    java.lang.Exception: try block
    Suppressed exception...
    java.lang.Exception: close()

    Before forwarding the exception thrown at  ---(*), to the enclosing catch block, The close() method which needs to get executed at the end of try block thats which an implementation of the MyResource, that was created with try, gets supressed. Do note that the method gets executed, but no exception thrown from this method gets caught. It gets suppressed as there's another exception thrown from try, which leaves that try block partially executed.

    Hence, the close() method, though still gets executed, but any exceptions in it can be caught, using the ,  Throwable[] t = e.getSuppressed(); as shown in the code above.

    ________________________________________________________
    'Nested try-catch':

    A try-block can contain another try-catch sequence.
    A catch block can contain another try-catch sequence too.
    A finally block can have try-catch blocks(multiple) in it.

    ________________________________________________________
    'custom Exception classes':

    A custom Excpetion class can be created in 2 ways:
    1) Extend Throwable class
    2) Extend any of Thowable's subclass such as Exception


    ___________________________________________________________________________