Saturday, January 17, 2009

What is new in Java 6.0 Collections API?

Introduction

In this article I will write about the new Collections APIs introduced in Java 6.0. Mustang has few interesting changes in the Collections APIs, one amoung them is the Deque. Deque is used for the Bi-Directional traversal. It has different implementations including BlockingDeque,ArrayDeque,etc. I will talk about the Deque and its various implementation, also few more changes in the Collectiona API in Java 6.0.

Java 6.0 New Collection APIs an Overview

The following are the new collection APIs introduced in Java 6.0. I listes them as Interfaces and classes.
New Interfaces

Deque
BlockingDeque
NavigableSet
NavigableMap
New Classes

ArrayDeque
LinkedBlockingDeque
ConcurrentSkipListSet
ConcurrentSkipListMap
AbstractMap.SimpleEntry
AbstractMap.SimpleImmutableEntry
Updated Classes in Java 6.0

LinkedList
TreeSet
TreeMap
Collections
Deque and ArrayDeque

Deque is the abbreviation of “Double Ended Queue”. A Collection that allows us to add (or) remove elements at both ends. Deque supports total size of collection for both fixed and unspecified size limits.

Deque implementation can be used as Stack(Last in first out ) or Queue(First in First Out).For each insertion, retrieval and removal of elements from deque there exists methods in 2 flavours. One will throw exception if it fails in an operation and another one returns status or special value for each operation.

Operation Special value method Exception throwing method
Insertion at head offerFirst(e) addFirst(e)
Removal at head pollFirst() removeFirst()
Retrieval at Head
peekFirst() getFirst()
Insertion at Tail offerLast(e) addLast(e)
Removal at Tail pollLast() removeLast()
Retrieval at Tail
peekLast() getLast()
Implementation of Deque doesn’t require preventing the insertion of null, but when we are using special value method null is return to indicate that collection is empty. So it is recommendable not to allow insertion of null.

ArrayDeque is a class that implements Deque. It has no capacity restrictions. It will perform faster than stack when used as stack and faster than linked list when used as queue. ArrayDeque is not thread Safe. The following example explains how to write program using ArrayDeque.

Example
import java.util.ArrayDeque;
import java.util.Iterator;

public class DequeExample
{
public static void main(String as[])
{
ArrayDeque adObj = new ArrayDeque(); 

//Insertion by using various methods
adObj.add("Oracle"); 
adObj.addFirst("DB2");
adObj.offerFirst("MySQL");   //returns boolean - true R false 
adObj.offerLast("Postgres");   //returns boolean - true R false

//Retrievals 
System.out.println("Retrieving First Element :" + adObj.peekFirst());
System.out.println("Retrieving Last Element  :"+ adObj.peekLast());

//Removals
System.out.println("Removing First  Element  :"+ adObj.pollFirst());
System.out.println("Removing Last  Element   :"+ adObj.pollLast());

//Reverse traversal
System.out.println("Remaining Elements :");
Iterator it = adObj.descendingIterator();
while(it.hasNext())
{
System.out.println(it.next());
}  
}
}
Output:
Retrieving First Element :MySQL
Retrieving Last Element  :Postgres
Removing First  Element  :MySQL
Removing Last  Element   :Postgres
Remaining Elements :
Oracle
DB2
BlockingDeque and LinkedBlockingDeque

A BlockingDeque is similar to Deque and provides additionally functionality. When we tries to insert an element in a BlockingDeque, which is already full, it can wait till the space becomes available to insert an element. We can also specify the time limit for waiting.

BlockingDeque methods available in four flavours

Methods throws exception
Methods returns special value
Methods that blocks(Waits indefinitely for space to available)
Methods that times out(Waits for a given time for space to available)
Operation Special Value Throws Exception Blocks Times out
Insertion at head addFirst(e) offerFirst(e) putFirst(e) offerFirst(e,time,unit)
Removal from head removefirst() pollFirst() takeFirst() takeFirst(time,unit)
Retrieval from head getFirst() peekfirst() NA NA
Insertion at tail addLast(e) offerLast(e) putLast(e) offerLast(e,time,unit)
Removal from tail removeLast() pollLast() takeLast() takeLast(time,unit)
Retrieval from tail getLast() peekLast() NA NA
A LinkedBlockingDeque is a Collection class, which implements BlockingDeque interface in which we can specify maximum capacity if we want.If we did not specify the capacity then maximum capacity will be Integer.MAX_VALUE.
import java.util.concurrent.*;
class BlockingDequeExample implements Runnable
{
LinkedBlockingDeque lbd = new LinkedBlockingDeque(1);
volatile boolean b = true;
public void run()
{
try
{
/*First thread once enters into the block it modifies 
instance variable b to false and prevents second 
thread to enter into the block */
if(b)
{
b = false;
Thread.sleep(5000);//Makes the Thread to sleep for 5 seconds
System.out.println("Removing "+lbd.peek());
lbd.poll();//Removing an element from collection
}
else
{
System.out.println("Waiting "); 
/*This method makes to wait till the first thread removes an elements*/
lbd.put("B"); 
System.out.println("Inserted "+lbd.peek()); 
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
public static void main(String[] args) throws Exception
{
BlockingDequeExample bdeObj = new BlockingDequeExample();
bdeObj.lbd.offer("A");
System.out.println("Inserted "+bdeObj.lbd.peek()); 
Thread tMainObj = new Thread(bdeObj);
tMainObj.start();
Thread tSubObj = new Thread(bdeObj);
tSubObj.start();  
}
}
Output:
Inserted A
Waiting
Removing A
Inserted B
NavigableSet and ConcurrentSkipListSet

Suppose we have a requirement, from sorted set elements [5,10,15,20] we want few things like this

Retrieve the element which is immediately greater than or lower than element 15
Retrieve all elements greater than or lower than 10
With the help of existing methods we need to take few risks to achieve them. But with NavigableSet methods it becomes just a method call.NavigableSet methods used to return the closest matches of elements for the given elements in the collection. ConcurrentSkipListSet is one of the class that implements NavigableSet.

Example
import java.util.concurrent.*;
import java.util.*;
class SkipListSetTest 
{
public static void main(String[] args) 
{
ConcurrentSkipListSet csls = new ConcurrentSkipListSet();
csls.add(15);
csls.add(20);
csls.add(5);
csls.add(10);
System.out.println("Elements in the collections are");
for(Integer i: csls)
{
System.out.println(i);
}
/* Retrieve immediate element less than or equal to  the given element */
System.out.println("Floor    "+csls.floor(12));
/* Retrieve immediate  element greater than or equal to the given element */
System.out.println("Ceiling  "+csls.ceiling(12));
/* Retrieve immediate element less than the given element */
System.out.println("Lower    "+csls.lower(10));
/* Retrieve immediate element greater than the given element */
System.out.println("heigher  "+csls.higher(10));
System.out.println("Head Elements ");
Set cslsHeadView =  csls.headSet(10);
//HeadSet excludes the given element
for(Integer i: cslsHeadView)
{
System.out.println(i);
}
Set cslsTailView =  csls.tailSet(10);
//TailSet includes the given element
System.out.println("Tail Elements");
for(Integer i: cslsTailView)
{
System.out.println(i);
}
}
}
Output:
Elements in the collections are
5
10
15
20
Floor    10
Ceiling  15
Lower    5
heigher  15
Head Elements
5
Tail Elements
10
15
20
NavigableMap and ConcurrentSkipListMap

NaviagableMap is similar to NaviagableSet. In NavigableSet, methods use to return values, but in NaviagableMap methods used to return the key,value pair.ConcurrentSkipListMap is the one of the class which implements NaviagableMap.

import java.util.*;
import java.util.concurrent.*;

class NavigableMapExample 
{
public static void main(String[] args) 
{
NavigableMap nm = new ConcurrentSkipListMap();
nm.put(1,"One");
nm.put(2,"Two");
nm.put(3,"Three");
nm.put(4,"Four");
nm.put(5,"Five");
/* Retrieves the key,value pair immediately lesser than the given key */
Map.Entry ae = nm.lowerEntry(5);
/* Map.Entry is a Static interface nested inside Map 
interface,just use to hold key and value */
System.out.println("Key" + ae.getKey());
System.out.println("Value"+ ae.getValue());
/* Retrieves key,value pairs equal to and greater then the given key */
SortedMap mm = nm.tailMap(3);
Set s = mm.keySet(); 
System.out.println("Tail elements are");
for(Integer i:s)
{
System.out.println("Key "+ i + "Value "+ mm.get(i));
}
}
}
output
Key 4
Value Four
Tail elements are
Key 3  Value Three
Key 4  Value Four
Key 5  Value Five
Notes :
floorEntry method retrieves less than or equal to the givenkey (or) null
lowerEntry method retrieves always less than the givenkey (or) null
headMap method retrieves all elements less than the givenkey
tailMap method retrieves all elements greater than or equal to the givenkey
AbstractMap.SimpleEntry and AbstractMap.SimpleImmutableEntry

AbstractMap.SimpleEntry and AbstractMap.SimpleImmutableEntry are a static classes nested inside abstractMap class.The instance of this classes use to hold the key,value pair of one single entry in a Map.The difference between these two classes is that former one allow us to set the value and later one if we try to set the value, it throws UnsupportedOperationException

Modified classes

Classes are modified to implement the new interfaces in the existing classes.LinkedList is modified to implement Deque. TreeSet is modified to implement NavigableSet.TreeMap is modified to implement NavigableMap.In Collections 2 new methods newSetFromMap and asLifoQueue are added.

Conclusion

With java6.0 collections bi- directional traversal becomes easier and retrieval of elements in our desired way also possible. Some attention is also given towards Concurrent operations in Collection.

No comments: