A Queue interface is one of the widely used Collection interfaces. Queue interface as shown in the below figure extends Collection interface, and hence it inherits all the operations from Collection interface. Queue, in general is a very popular data structure that is used in many scenarios. More details about Queue is available in our data structures module; understanding data structure Queue.
Queue, typically follows the FIFO (first in first out) semantics. The elements that inserted first into the queue are removed first. This is opposite to an other very popular data structure "Stack", which follows the LIFO (last in first out) semantics , more details about Stack is available here understanding data structure Stack. Elements into the Queue are always inserted at the "tail" of the Queue and removed from the "head" of the Queue. Both "head" and "tail" points to the same position when the Queue is empty.
There is a long list of interfaces and classes that are derived from Queue interface;s we will cover them in the next sections. One such interface is "BlockingQueue" interface". In general, Queue interface does not define blocking queue methods, which are very commonly used in concurrent programming. Blocking queue methods, while adding an element in the queue, "waits" for the space to become available if the Queue is FULL. At the same time, Blocking Queue methods "wait" for the Queue to be non-empty, when tries to add an element from the Queue. Generic Queue interface does not offer this kind of behavior, more details about blocking Queue is available here Understanding Blocking Queue. The other important property of the Queue interface, is that it does not allow insertion of "null" elements in to the Queue.
The Queue interface inherits all the methods from the Collection interface, but as we know Queue has its own constraints/properties that are different from the other Collection interfaces. Accordingly, Queue interface defines few methods, on top of the ones inherited from the Collection interface.
Queue interface offers two sets of methods for the same functionality. One set of methods throws an "exception" on failure while the other set does not throw an exception. Instead it lets the caller know the result by returning an appropriate value.
Method | Description |
---|---|
boolean add(E e) | Inserts the specified element "e" into the Queue immediately. Returns True on success and throws an Exception if the Queue is full. Throws "illegalStateException" if the Queue is full. |
E remove() | Retrieves and removes the element from the head of the Queue immediately. Returns the "removed element" on success and throws an Exception if the Queue is empty. Throws "NoSuchElementException" if the Queue is empty. |
E element() | Retrieves, but "does not" remove the element from the head of the Queue immediately. Returns the "retrieved element" on success and throws an Exception if the Queue is empty. Throws "NoSuchElementException" if the Queue is empty. |
boolean offer(E e) | Inserts the specified element "e" into the Queue immediately. Returns True on success and false if the Queue is full. |
E poll() | Retrieves and removes the element from the head of the Queue immediately. Returns the "removed element" on success or "null" if the Queue is empty. |
E peek() | Retrieves, but "does not" remove the element from the head of the Queue immediately. Returns the "retrieved element" on success or "null" if the Queue is empty. |
Let us see an example program that demonstrates the usage of the above mentioned methods. The example have used LinkedList, one of the implementation classes of Queue and demonstrated the usage of the methods defined by the Queue interface. LinkedList implements List interface and also Queue interface, LinkedList is discussed in detail here understanding LinkedList.
import java.util.Iterator; import java.util.LinkedList; import java.util.Queue; public class QueueInterfaceDemo { public static void main(String[] args) { Queue qobj = new LinkedList(); qobj.add(300); qobj.add("200"); qobj.add("e3"); System.out.print(" Just Retrieve(No removal) the element from Queue, "); System.out.println(" First Element: " + qobj.element()); System.out.println(" All Queue Elements: " + qobj); System.out.print(" Retrieve and remove the element from Queue, "); System.out.println(" First Element: " + qobj.remove()); System.out.println(" All Queue Elements: " + qobj); Iterator iterobj = qobj.iterator(); System.out.println(" Retrieve/remove all the elements of the Queue"); while(iterobj.hasNext()) { System.out.println("\t Queue element " + qobj.poll()); } System.out.println(" Try Retrieving the element from the Queue"); try { System.out.println(" First Element: " + qobj.element()); } catch (Exception e) { System.out.println(" Exception Handled: Queue Empty !"); } System.out.println(" First Element: " + qobj.peek()); } }
The above program demonstrates the usage of the methods defined in the Queue interface. As we know, Queue interface offers two sets of methods for the same functionality, one set which throws exceptions while the other set of methods does not. As you can in the output below, the methods peek and element do the same thing, try to retrieve the element, though the method "element" throws an exception when the Queue is empty. Hence the second usage of the element() method, in the above program is guarded with a try/catch block. Also, notice the output below, the method peek() returns null when the Queue is empty.
Let us Compile/run the program, Here is the output:
Just Retrieve(No removal) the element from Queue, First Element: 300 All Queue Elements: [300, 200, e3] Retrieve and remove the element from Queue, First Element: 300 All Queue Elements: [200, e3] Retrieve/remove all the elements of the Queue Queue element 200 Queue element e3 Try Retrieving the element from the Queue Exception Handled: Queue Empty ! First Element: null