Popular Posts

JDK7 Highlights & Hashing Techniques

Seven New Features in Java(JDK7) Programming Language

1.    Binary Literals
In Java SE 7, the integral types (byte, short, int, and long) can also be expressed using the binary number system. To specify a binary literal, add the prefix 0b or 0B to the number. The following examples show binary literals:

 int a=010; // will give 10   (upto JDK6)
 int b=  ob010;  will give 2. ( in JDK7 it will consider as binary literal)

2.    try with resource statement
try ( Autoclosable Implementation class) {}

 Any object which implements AutoCloseable/ Cloneabl interface can be passed to try(){} block. but this no where related to try catch Exception handling one. this is useful for IO Streams ,JDBC where we need to close the connections after using it. try() will take care of closing operations.

 class MyCustomClosable implements AutoCloseable,Cloneable{

       @Override
       public void close() throws Exception {}
  }
Ex: try(MyCustomClosable  c=new MyCustomClosable()){}

Ex: try (BufferedReader br = new BufferedReader(new FileReader(path))) {
     return br.readLine();
       }


3.     switch case allow string as an case element but it is case sensitive

              String key = "Hello";
              switch (key) {
              case "hello":
                     System.out.println("hello");
                     break;
              case "Hello":
                     System.out.println("Hello");
                     break;
              default:
                     System.out.println("Not Matching");
                     break;
              }

      
4.    Underscore (_) in digits just for readability of lengthy values.
   int a=30500; and   int a=30_500; are equal in JDK7//  this is just for readability purpose

5.    Catching Multiple Exceptions and Re-throwing Exceptions with improved Type Checking

adding multiple exceptions in same block with logical OR 
catch (IOException|SQLException ex) {
    logger.log(ex);
    throw ex;
}
 
  
Re-Throwing of exceptions in catch Block.
public void rethrowException(String exceptionName)
  throws FirstException, SecondException {
      try {
      // ...
    }
    catch (Exception e) {
      throw e;
    }
  }

 
6.    Type Inference for generic instance creation

Map<String, List<String>> myMap = new HashMap<String, List<String>>();
In Java  7, you can substitute the parameterized type of the constructor with an empty set of type parameters (<>):
Map<String, List<String>> myMap = new HashMap<>(); is valid without any warnings.
This pair of angle brackets is informally called the diamond.
 

7.    Varags  @SafeVaras annotation Non-Reifiable

Heap Pollution
Most parameterized types, such as ArrayList<Number> and List<String>, are non-reifiable types. A non-reifiable type is a type that is not completely available at runtime. At compile time, non-reifiable types undergo a process called type erasure during which the compiler removes information related to type parameters and type arguments. This ensures binary compatibility with Java libraries and applications that were created before generics. Because type erasure removes information from parameterized types at compile-time, these types are non-reifiable.
Heap pollution occurs when a variable of a parameterized type refers to an object that is not of that parameterized type. This situation can only occur if the program performed some operation that would give rise to an unchecked warning at compile-time. An unchecked warning is generated if, either at compile-time (within the limits of the compile-time type checking rules) or at run-time, the correctness of an operation involving a parameterized type (for example, a cast or method call) cannot be verified.
@SafeVarargs
Unlike the @SuppressWarnings annotation, the @SafeVarargs annotation is a documented part of the method's contract; this annotation asserts that the implementation of the method will not improperly handle the varargs formal parameter.
@SafeVarargs
       public static <T> void addToList3(List<T> listArg, T... elements) {
              for (T x : elements) {
                     listArg.add(x);
              }
       }


Java Collections Important Points

How HashSet, HashMap works in java
HashSet will internally instantiate HashMap to store data.
When you create HashSet instance it will call the default constructor of HashSet as shown below. Both these (HashSet, HashMap) have default initial capacity 16.
  
HashSet<String> s=new HashSet<>();
   Which internally calls the below code
public HashSet() {
map = new HashMap<>();
}     Where map is transient           

All the Rules of HashMap are applicable to HashSet. Hence Below section I focused on the HashMap only.

HashMap internally uses two data structures to store data.
1.    Array  à Entry[] table=new Entry[16];
2.    LinkedList à Each Entry Object instance act as Node in the LinkedList

Entry Object is having following instance variables
i)             key will store reference to KEY
ii)            value will store reference to value
iii)           hash will store hashcode generated by Hash function
iv)           next will store reference to the next Node
                
How put method works in java HashMap
·         When you call put (KEY, VALUE) method on HashMap Object, it will take hashCode of KEY. And it will generate new hash Based on KEY hashCode.

IMP: Applies a supplemental hash function to a given hashCode which defends against poor quality hash functions,  This is critical because HashMap uses power-of-two length hash tables, that otherwise encounter collisions for hashCode that do not differ in lower bits.

·         Bucket index is calculated as index= hash * (table.length-1);
·         Each index of array is a bucket.  i.e. table[i]
·         To identify the bucket for any <key,value>, Hash map use KEY.hashCode() and perform some operation:


Bucket (index) =HashMap.indexFor (HashMap.hash(key.hashCode()), entryArray.length);
It means, two keys with same hashCode can fall under same bucket.
·         if a bucket is empty (table[i] is null) then the Entry object is simply inserted at ith position as shown in the below image at 0,2,3,5,6 locations.
table[i] = new Entry(hash, key, value, null)
·         If a bucket has some values, then the following algo is used:
 Entry entry = table[i]
table[i] = new Entry (hash, key, value, entry) 
      It means, the latest entry resides on the top of the bucket. In Image 1,4 locations
·         If a key already exists in a map, then it just replace the value and return the old value
if(entry.key == key || key.equals(entry.key)  )then
Object oldValue = entry.value;
Entry.value = newValue;
Return oldValue;
end if
·         In case of new key,  map add the key, value (a new Entry object with key value) and return null
·         Entry.hash is not the hashCode of key, but HashMap use its own hash algorithm to create hash based on key.hashCode(). So it's like:
entry.hash = HashMap.hash(key.hashCode());

·         HashMap allow single null as key. For Null keys always map to hash 0, thus index 0. Means if   KEY is null its hashCode takes as 0 and insert at index of 0.







How get method works

1.    Read the hashCode of KEY object and get the index value using that index it will iterate for loop get the required value as shown below
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;
}


SOME IMPORTANT POINTS ON JAVA COLLECTIONS
àHashMap allows null/duplicate KEYs.  But most recently inserted value only exists in the Value if and only if equals method of newly inserted KEY returns true.
àHashtable will throw NullPointerException when inserted KEY is null.
àHashMap does not guarantee that the order of the map will remain constant over time.
àWhen you call add method it will override the existing KEY if any. And return Boolean.

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

Here PRESENT is simple java static Object instance
private static final Object PRESENT = new Object();

àArrayList default size is 10

ArrayList<String> arrayList=new ArrayList<String>();

private transient Object[] elementData;

public ArrayList() {
         this(10);
}

 public ArrayList(int initialCapacity) {
         super();
       if (initialCapacity < 0)
           throw new IllegalArgumentException("Illegal Capacity: "+
                                              initialCapacity);
         this.elementData = new Object[initialCapacity];
 }

     
àSystem.out.println () will internally calls print () which again call write method.
Which is synchronized and BufferedWriter to write text

àLinkedList uses nodes to store data and each node is having pointer to previous node and next node java LinkedList uses Double-Linear Lined List.

à LinkedList uses Double-LinkedList and HashMap uses Arrays, Single-LinkedList Algorithms.


àIn LinkedList add & addList method will do the same. Whereas addBefore method will insert at starting point, All three methods will call internally addBefore (element, Entry); method.

àPriorityQueue is having similar to LinkedList but it will take argument of comparator

   public PriorityQueue(int initialCapacity,
                        Comparator<? super E> comparator) {
       // Note: This restriction of at least one is not actually needed,
       // but continues for 1.5 compatibility
       if (initialCapacity < 1)
           throw new IllegalArgumentException();
       this.queue = new Object[initialCapacity];
       this.comparator = comparator;
   }

         
à How can ArrayList be synchronized without using Vector?
 Arraylist can be synchronized using:
Collection.synchronizedList(List list)
Other collections can be synchronized:
Collection.synchronizedMap(Map map)
Collection.synchronizedCollection(Collection c)


àWhen you use Tree Based Collections (TreeMap, TreeSet)

1.    KEY must not be null value.
2.    KEY must implement Comparable interface.
TreeMap<Data, Integer> kv = new TreeMap<Data, Integer>();

Class Data implement Comparable{   // compareTo(){}}
             
(OR)
While Instantiating TreeMap you must pass Comparator of KEY type to TreeMap constructor argument.


 TreeMap<Data, Integer> kv = new TreeMap<Data, Integer>(
                                       new MyComparator());

class MyComparator implements Comparator<Data> {
          @Override
          public int compare(Data o1, Data o2) {    return 0;}
}


àWhen to use ArrayList or LinkedList?
 Adding new elements is pretty fast for either type of list. For the ArrayList, doing random lookup using "get" is fast, but for LinkedList, it's slow. It's slow because there's no efficient way to index into the middle of a linked list. When removing elements, using ArrayList is slow. This is because all remaining elements in the underlying array of Object instances must be shifted down for each remove operation. But here LinkedList is fast, because deletion can be done simply by changing a couple of links. So an ArrayList works best for cases where you're doing random access on the list, and a LinkedList works better if you're doing a lot of editing in the middle of the list.


No comments:

Post a Comment