Follow me

Saturday, November 23, 2013

Things must know about java collection API - Part IV

24 . Collection Name
abstract class  java.util.EnumSet
Implementation Of
extends AbstractSet<E> implements Cloneable, java.io.Serializable
Is Ordered
No
Is Resizable
Yes
Is Thread Safe
No. but can use  Collections.synchronizedSet(java.util.Set)
Duplicate allowed
No
Null allowed
No
Iterate Logic
The iterator returned by the iterator method traverses the elements in their natural order (the order in which the enum constants are declared).
Complexity
EnumSet is a high performance Java Collection. It provides O(1) performance for add(), contains() and next() operations because of array based access. Preferably, use EnumSet over HashSet for storing Enum constants.
More info

ü  A specialized Set implementation for use with enum types.

ü  All of the elements in an enum set must come from a single enum type that is specified, explicitly or implicitly, when the set is created.

ü   Enum sets are represented internally as bit vectors[Vector of n zero-one (false-true) bits. This adds some convenient constructors and methods to the BitSet class]

ü  The space and time performance of this class should be good enough to allow its use as a high-quality, typesafe alternative to traditional int-based "bit flags."

ü  EnumSet are likely (though not guaranteed) to be much faster than their HashSet counterparts. Even bulk operations, such as addAll() and AbstractSet.removeAll(java.util.Collection) execute in constant time if the parameter is another EnumSet instance.

ü  EnumSet class is that it doesn't have a public constructor. Instead, there are some static methods to automatically create an enum set for some given criteria. These methods include:

·         EnumSet.of() method is overloaded for common usage, which tends to perform better than variable argument version, and can be added for flexibility to create enum with any number of instances

·         complementOf(EnumSet s) - Creates an enum set with the same element type as the specified enum set, initially containing all the elements of this type that are not contained in the specified set.

·         copyOf(Collection c) - Creates an enum set initialized from the specified collection.

·         copyOf(EnumSet s) - Creates an enum set with the same element type as the specified enum set, initially containing the same elements (if any).

·         noneOf(Class elementType) - Creates an empty enum set with the specified element type.

·         range(E from, E to) - Creates an enum set initially containing all of the elements in the range defined by the two specified endpoints.

ü  Various creation methods that simplify the construction of a set based on an Enumeration

ü  Guaranteed ordering of the elements in the set based on their order in the enumeration constants are declared

ü  Performance and memory benefits not nearly possible with a regular set implementation

ü  EnumSet also presents a good example of the Factory method design pattern to create instances.

ü  EnumSet is provides two concrete implementations, java.util.RegularEnumSet and java.util.JumboEnumSet. The main difference between the two is that the former uses a long variable to store elements while later uses a long[] to store its element. Since RegularEnumSet uses long variable, which is a 64 bit data type, it can only hold that much of an element. That's why when an empty EnumSet is created using EnumSet.noneOf()method. It chooses RegularEnumSet if the key universe (number of enum instances in Key Enum) is less than or equal to 64. It chooses JumboEnumSet if the key universe is more than 64.




























































































package com.study.collection;

import java.util.*;

public class EnumSetDemo {

   // create an enum
   public enum Numbers {

      ONE, TWO, THREE, FOUR, FIVE
   };

   public static void main(String[] args) {

      // create a  list that will be used like args
     Numbers[] list = {Numbers.ONE,Numbers.TWO, Numbers.THREE, Numbers.FOUR, Numbers.FIVE};
     EnumSet<Numbers> set1 = EnumSet.of(Numbers.ONE, list);
     System.out.println("Set 1:" + set1);
     EnumSet<Numbers> set2 = EnumSet.of(Numbers.FIVE, list);
     System.out.println("Set 2:" + set2);
     //2 is not available..still chk
     set1.remove(Numbers.TWO);
     System.out.println("Set 1 remove 2 : " + set1);
     set2.remove(Numbers.FIVE);
     System.out.println("Set 2 remove 5 : " + set2);
        
    
   }

}
O/P

Set 1:[ONE, TWO, THREE, FOUR, FIVE]
Set 2:[ONE, TWO, THREE, FOUR, FIVE]
Set 1 remove 2 : [ONE, THREE, FOUR, FIVE]
Set 2 remove 5 : [ONE, TWO, THREE, FOUR]




25.  Collection Name
java.util.HashSet
Implementation Of
extends AbstractSet<E>
 implements Set<E>, Cloneable, java.io.Serializable
Is Ordered
No
Is Resizable
Yes
Is Thread Safe
No
Duplicate allowed
No
Null allowed
This class permits the null element.
Iterate Logic
Iterator<E> iterator() or toArray() methods
Complexity
A HashSet gives you O(1) for adding, removing and checking for presence. For actually finding objects it's an O(n) operation..
More info
ü  This class implements the Set interface, backed by a hash table (actually a HashMap instance).

ü  Iterating over this set requires time proportional to the sum of the HashSet instance's size (the number of elements) plus the "capacity" of the backing HashMap instance (the number of buckets). Thus, it's very important not to set the initial capacity too high (or the load factor too low) if iteration performance is important.

ü  A Set implements Collection which Map does not. Therefore a HashSet must maintain some iterable reference to the elements. It uses the Map to check for existence but must still add the element to the iterable collection so hashmap faster than hashset

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

ü  Since HashSet use HashMap internally and HashMap need key and value object so where this key comes from so the answer is
The answer is, the key is a the value that is passed into the the hashset and
value = "new Object()". The Value is a dummy object which is in fact a static constant so that each add operation does not create a dummy instances of Object.

When you iterate over the internal HashMap, the iteration will be over the keySet of the hashMap.


package com.study.collection;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;

public class HashSetDemo {

     /**
      * @param args
      */
     public static void main(String[] args) {

          HashSet<String> h = new HashSet<String>();
          h.add("one");
          h.add(new String("one"));
          h.add("ONE");
          System.out.println("Only Unique = " + h);

          List<String> list = new ArrayList<String>();
          list.add("obj 1");
          list.add("obj 2");
          list.add("obj 3");
          h.addAll(list);
          System.out.println("Iteration .. insertion order may not maintained");
          Object[] array = h.toArray();
          for (Object obj : array) {
              System.out.println((String) obj);
          }
           h.retainAll(list);
          System.out.println("after retainAll(list)  = "+ h);
          //h.removeAll(list);
          System.out.println("After removal = "+ h);
          h.removeAll(list);
          System.out.println("After remove all = " + h );
         
     }

}
O/P
Only Unique = [ONE, one]
Iteration .. insertion order may not maintained
ONE
obj 3
obj 2
obj 1
one
after retainAll(list)  = [obj 3, obj 2, obj 1]
After removal = [obj 3, obj 2, obj 1]
After remove all = []




26. Collection Name
java.util. LinkedHashSet
Implementation Of
extends HashSet<E> implements Set<E>, Cloneable, Serializable
Is Ordered
Yes
Is Resizable
Yes
Is Thread Safe
No but can be.. Set s = Collections.synchronizedSet(new LinkedHashSet(...));
Duplicate allowed
No
Null allowed
Yes
Iterate Logic
Iterator<E> iterator();
Complexity
O(1) time complexity for adding and removing. For actually finding objects it's an O(n) operation.
More info
ü  Hash table and linked list implementation of the Set interface, with predictable iteration order

ü  This implementation differs from HashSet in that it maintains a doubly-linked list running through all of its entries. This linked list defines the iteration ordering, which is the order in which elements were inserted into the set (insertion-order).

ü  Performance is likely to be just slightly below that of HashSet, due to the added expense of maintaining the linked list, with one exception: Iteration over a LinkedHashSet requires time proportional to the size of the set, regardless of its capacity. Iteration over a HashSet is likely to be more expensive, requiring time proportional to its capacity.

ü  Iterating over a HashSet you need (pretty much) iterate over the buckets that contain the elements, then to eliminate empty values, which requires additional time. Briefly - there is some overhead associated with sorting empty elements out.

ü  The nature of Linked collections is so that every element points to the next one. So, you start with the first and without much problems pull the next, and so on - this way you easily iterate them all.

ü  LinkedHashSet internally use LinkedHashMap. Default initial capacity is 16 with load factor .75f

public LinkedHashSet() {
    super(new LinkedHashMap<E, Object>(16, .75f));
}




package com.study.collection;

import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
public class LinkedHashSetDemo {

     public static void main(String[] args) {
          HashSet<String> hs = new HashSet<String>();
          hs.add("One");
          hs.add("Two");
          hs.add("Three");
          //Creating LinkedHashSet from HashSet
          LinkedHashSet lhs = new LinkedHashSet(hs);
          //This will be ordered
          lhs.add("Four");
          lhs.add("Five");
          lhs.add("Six");
         
          System.out.println("Element added after adding lhs collection will be ordred");
          Iterator iter = lhs.iterator();
          while(iter.hasNext()){
              System.out.println(iter.next());
          }
    
     }
}

O/P
Element added after adding lhs collection will be ordred
Three
One
Two
Four
Five
Six



27. Collection Name
java.util.TreeSet
Implementation Of
extends AbstractSet<E> implements NavigableSet<E>, Cloneable, Serializable
Is Ordered
Yes. The elements are ordered using their natural ordering, or by a Comparator provided at set creation time
Is Resizable
Yes
Is Thread Safe
No.  SortedSet s = Collections.synchronizedSortedSet(new TreeSet(...));
Duplicate allowed
No
Null allowed
No
Iterate Logic
Iterator<String> itr = ts.iterator();
Complexity
Log(n)
More info
ü  Ordering maintained by a set (whether or not an explicit comparator is provided) must be consistent with equals if it is to correctly implement the Set interface. (See Comparable or Comparator for a precise definition of consistent with equals.)

ü  TreeSet is bit slower  than other set because of sorting operation it needs to perform on each insertion. 

ü  TreeSet is backed up by NavigableMap in Java and by default it uses TreeMap.

ü  Since TreeSet uses compareTo() method of respective elements to compare them  which throws NullPointerException while comparing with null.

ü  offers a few handy methods to deal with the ordered set like first(), last(), headSet(), and tailSet() etc

ü  TreeSet and TreeMap oddly have nothing to do with representing trees. Internally they use a tree organization to give you an alphabetically sorted Set/Map, but you have no control over links between parents and children.




import java.util.Comparator;
import java.util.TreeSet;

public class TreeSetDemo {

     /**
      * @param args
      */
     public static void main(String[] args) {
          // By using name comparator (String comparison)

          // TreeSet nameComp1 = new TreeSet();
          // nameComp1.add(null);

          System.out.println("===By using Name comparator=====");

          TreeSet<Empl> nameComp = new TreeSet<Empl>(new MyNameComp());
          nameComp.add(new Empl("C", 3000));
          nameComp.add(new Empl("B", 6000));
          nameComp.add(new Empl("K", 2000));
          nameComp.add(new Empl("D", 2400));
          nameComp.add(new Empl("D", 2400));
          for (Empl e : nameComp) {
              System.out.println(e);
          }

          System.out.println("===By using salary comparator=====");
          // By using salary comparator (int comparison)
          TreeSet<Empl> salComp = new TreeSet<Empl>(new MySalaryComp());
          salComp.add(new Empl("A", 3000));
          salComp.add(new Empl("B", 6000));
          salComp.add(new Empl("C", 2000));
          salComp.add(new Empl("D", 2400));
          for (Empl e : salComp) {
              System.out.println(e);
          }

          System.out.println("=======================");
          System.out.println("First Element " + salComp.first());
          System.out.println("First Element " + salComp.last());
          // Remove first element
          System.out.println("Removed = " + salComp.pollFirst());
          System.out.println("After delete = " + salComp);

     }

}

class MyNameComp implements Comparator<Empl>{

     @Override
     public int compare(Empl e1, Empl e2) {
          return e1.getName().compareTo(e2.getName());
     }
}   

class MySalaryComp implements Comparator<Empl>{

     @Override
     public int compare(Empl e1, Empl e2) {
          if(e1.getSalary() > e2.getSalary()){
              return 1;
          } else {
              return -1;
          }
     }
}

class Empl{
    
     private String name;
     private int salary;
    
     public Empl(String n, int s){
          this.name = n;
          this.salary = s;
     }
    
     public String getName() {
          return name;
     }
     public void setName(String name) {
          this.name = name;
     }
     public int getSalary() {
          return salary;
     }
     public void setSalary(int salary) {
          this.salary = salary;
     }
     public String toString(){
          return "Name: "+this.name+"-- Salary: "+this.salary;
     }
}


O/P

===By using Name comparator=====
Name: B-- Salary: 6000
Name: C-- Salary: 3000
Name: D-- Salary: 2400
Name: K-- Salary: 2000
===By using salary comparator=====
Name: C-- Salary: 2000
Name: D-- Salary: 2400
Name: A-- Salary: 3000
Name: B-- Salary: 6000
=======================
First Element Name: C-- Salary: 2000
First Element Name: B-- Salary: 6000
Removed = Name: C-- Salary: 2000
After delete = [Name: D-- Salary: 2400, Name: A-- Salary: 3000, Name: B-- Salary: 6000]



28 Collection Name
Interface java.util.NavigableSet
Implementation Of
extends SortedSet<E>
Is Ordered
Yes . A NavigableSet may be accessed and traversed in either ascending or descending order
Is Resizable
Yes
Is Thread Safe
No
Duplicate allowed
No
Null allowed
No
Iterate Logic
Iterator<String> itr = ts.iterator();
Complexity
O(n)
More info

ü  The java.util.NavigableSet is nothing but an interface that is subtype of the java.util.SortedSet

ü  A SortedSet extended with navigation methods reporting closest matches for given search targets. Methods lower, floor, ceiling, and higher return elements respectively less than, less than or equal, greater than or equal, and greater than a given element, returning null if there is no such element.

ü  This interface additionally defines methods pollFirst and pollLast that return and remove the lowest and highest element, if one exists, else returning null. Methods subSet, headSet, and tailSet differ from the like-named SortedSet methods in accepting additional arguments describing whether lower and upper bounds are inclusive versus exclusive. Subsets of any NavigableSet must implement the NavigableSet interface.

ü  The objective of the descendingSet() is to fetch a NavigableSet thereby reversing the sequence or order of the elements compared to this one. Alterations to the set in the descending order are reflected in the original set of elements as well for the reason that the returned “view” has a back up of original NavigableSet

NavigableSet reverse = original.descendingSet();

ü  The task of the descendingIterator() method is to permit the iteration of elements in a reverse order or the sequence for the set NavigableSet, also known as the SortedSet and this is done with no need of altering the sequencing of elements.

            Iterator reverse = original.descendingIterator();



ü  A NavigableSet may be accessed and traversed in either ascending or descending order.







package com.study.collection;

import java.util.NavigableSet;
import java.util.TreeSet;

public class NevigableSetDemo {

     public static void main(String[] args) {

          NavigableSet original = new TreeSet();
          original.add("1");
          original.add("2");
          original.add("3");
          original.add("4");
          original.add("5");

         
          //this headset will contain "1", "2", and "3" because "inclusive"=true
          NavigableSet headset = original.headSet("2", true);
          System.out.println("headSet of 2 = " + headset); // HeadSet[1, 2]
          NavigableSet tailSet = original.tailSet("2", true);
          System.out.println("tailSet set of 2 = " + tailSet);// tailSet[2, 3, 4]
          System.out.println("headset.pollFirst() == " + headset.pollFirst());//1
         
          System.out.println("Subset of original 1,3  = " + original.subSet("1", "4") );
     }

}

O/P

headSet of 2 = [1, 2]
tailSet set of 2 = [2, 3, 4, 5]
headset.pollFirst() == 1
Subset of original 1,3  = [2, 3]



29. Collection Name
java.util.BitSet
Implementation Of
extends Object implements Cloneable, Serializable
Is Ordered

Is Resizable
Yes
Is Thread Safe
No
Duplicate allowed
No
Null allowed
Unless otherwise noted, passing a null parameter to any of the methods in a BitSet will result in a NullPointerException.
Iterate Logic

Complexity

More info
ü  This class implements a vector of bits that grows as needed.

ü  All bits in the set initially have the value false.


ü  Each component of the bit set has a boolean value. The bits of a BitSet are indexed by nonnegative integers. Individual indexed bits can be examined, set, or cleared. One BitSet may be used to modify the contents of another BitSet through logical AND, logical inclusive OR, and logical exclusive OR operations

ü  By default, all bits in the set initially have the value false.

ü  Every bit set has a current size, which is the number of bits of space currently in use by the bit set. Note that the size is related to the implementation of a bit set, so it may change with implementation. The length of a bit set relates to logical length of a bit set and is defined independently of implementation.

ü  BitSet internally use long array i.e. private long[] words; so the minimum size is 64 bits

ü  Size() returns the number of bits of space actually in use by this BitSet to represent bit values. The maximum element in the set is the size - 1st element

ü  length() returns the "logical size" of this BitSet: the index of the highest set bit in the BitSet plus one. Returns zero if the BitSet contains no set bits.

ü  Creates a bit set whose initial size is large enough to explicitly represent bits with indices in the range

public BitSet(int nbits) {
        // nbits can't be negative; size 0 is OK
        if (nbits < 0)
            throw new NegativeArraySizeException("nbits < 0: " + nbits);

        initWords(nbits);
        sizeIsSticky = true;
    }





package com.study.collection;

import java.util.BitSet;

public class BitSetDemo {

     /**
      * @param args
      */
     public static void main(String[] args) {
         
             BitSet bitSet1 = new BitSet();
            bitSet1.set(63);
            bitSet1.set(54);
          //  bitSet1.set(15);
            System.out.println("bitSet1 = " +bitSet1);
            System.out.println("size = "+bitSet1.size()+" length = "+bitSet1.length());
            for(int i=0;i<bitSet1.size();i++)
            {
                boolean bit = bitSet1.get(i);
                System.out.print(bit?1:0);
            }
           
          BitSet bits1 = new BitSet(16);
          BitSet bits2 = new BitSet(16);
          // set some bits
          for(int i=0; i<16; i++) {
          if((i%2) == 0) bits1.set(i);
          if((i%5) != 0) bits2.set(i);
          }
          System.out.println("Initial pattern in bits1: ");
          System.out.println(bits1);
          System.out.println("\\nInitial pattern in bits2: ");
          System.out.println(bits2);
          // AND bits
          bits2.and(bits1);
          System.out.println("\\nbits2 AND bits1: ");
          System.out.println(bits2);
          // OR bits
          bits2.or(bits1);
          System.out.println("\\nbits2 OR bits1: ");
          System.out.println(bits2);
          // XOR bits
          bits2.xor(bits1);
          System.out.println("\\nbits2 XOR bits1: ");
          System.out.println(bits2);
          }

    

}

O/P
bitSet1 = {54, 63}
size = 64 length = 64
0000000000000000000000000000000000000000000000000000001000000001Initial pattern in bits1:
{0, 2, 4, 6, 8, 10, 12, 14}
\nInitial pattern in bits2:
{1, 2, 3, 4, 6, 7, 8, 9, 11, 12, 13, 14}
\nbits2 AND bits1:
{2, 4, 6, 8, 12, 14}
\nbits2 OR bits1:

30. Collection Name
Interface java.util.Queue
Implementation Of
extends Collection<E>
Is Ordered

Queues typically, but do not necessarily, order elements in a FIFO (first-in-first-out) manner. Among the exceptions are priority queues, which order elements according to a supplied comparator, or the elements' natural ordering, and LIFO queues (or stacks) which order the elements LIFO (last-in-first-out). Whatever the ordering used, the head of the queue is that element which would be removed by a call to remove() or poll(). In a FIFO queue, all new elements are inserted at the tail of the queue. Other kinds of queues may use different placement rules. Every Queue implementation must specify its ordering properties.
Is Resizable
Yes
Is Thread Safe
No
Duplicate allowed
YES
Null allowed
No  throws java.lang.NullPointerException
Iterate Logic
iterator() : Iterator<E>
Complexity
NA
More info
ü  queues provide additional insertion, extraction, and inspection operations

ü  The offer method inserts an element if possible, otherwise returning false. This differs from the Collection.add method, which can fail to add an element only by throwing an unchecked exception. The offer method is designed for use when failure is a normal, rather than exceptional occurrence, for example, in fixed-capacity (or "bounded") queues.

ü  The remove() and poll() methods remove and return the head of the queue. Exactly which element is removed from the queue is a function of the queue's ordering policy, which differs from implementation to implementation. The remove() and poll() methods differ only in their behavior when the queue is empty: the remove() method throws an exception, while the poll() method returns null.

ü  The element() and peek() methods return, but do not remove, the head of the queue.T

ü  The Queue interface does not define the blocking queue methods, which are common in concurrent programming. These methods, which wait for elements to appear or for space to become available, are defined in the BlockingQueue interface, which extends this interface.

ü  All Known Implementing Classes:
AbstractQueue, ArrayBlockingQueue, ArrayDeque, ConcurrentLinkedQueue, DelayQueue, LinkedBlockingQueue, LinkedBlockingDeque, LinkedList, PriorityBlockingQueue, PriorityQueue, SynchronousQueue

ü  All Known Subinterfaces:
BlockingDeque<E>, BlockingQueue<E>, Deque<E>