This Tutorial Explains Java Collections Framework (JCF) in details along with Collection Hierarchy, Various Interfaces and the Advantages of JCF:
Hope these eloquent tutorials on this Java Series for beginners are really helpful in enriching your knowledge of Java.
Our previous tutorial briefed more on the basic I/O operations in Java. In this tutorial we will learn about Java Collections Framework (JCF) in detail.
Java Collections Framework (JCF) contains interfaces, abstract classes, and classes which can provide the architecture to store and manipulate a group of objects.
Table of Contents:
Video Tutorials On Java Collections Framework
Knowledge of Arraylist in Java:
Set Interface & Queue Interface in Java with Real-time examples:
HashMap, TreeMap and HashTable in Java:
So far, we have seen variables that store different types of data. These are singular units and are not very helpful when you have huge amounts of data to store and deal with. As we know, data is the most important constituent of computer processing.
Your application must be able to extract and gather data, process it to find out useful information and also pass it to and fro so that it is used efficiently to reach the solutions.
In this software world, we store the data that needs to be structured in a particular fashion so that the software programs are able to store, read, process and finally output the results. This is done using data structures.
Almost all programming languages support data structures. The data structure can be defined as a structured representation of data. Programming languages provide API (Application Programming Interface) functions in order to manipulate the data structures.
Need For Collection Framework
Prior to Java 1.2, Java programming language supported data structures like arrays, vectors or hash tables. Performing operations on these data structures were not easy as there was no common interface that worked on these data structures.
Programmers used to find it difficult to write algorithms that would work for all the data structures and was a big hassle. There was a need for a common interface that would work consistently on all data structures and also carry out operations efficiently.
Later, Java came up with a collections framework which is a group of classes and interfaces consisting of various operations that can be performed on data structures.
In this Java Collections Tutorial, we will discuss the Java Collections Framework in general. We will explore each of the collection components in our upcoming tutorials.
Java Collections Framework
Before we define a Java Collections Framework, let’s get to know the meaning of collection and a framework.
A collection can be defined as a group of objects. A collection is usually a single unit consisting of more than one object. A framework is a software that has a ready-made functional interface or architecture and also contains a set of classes and interfaces to be used with the provided interface.
A collections framework is defined as a unified, ready-made architecture consisting of the below.
#1) Algorithms
These are methods or set of statements that can aid programmers in searching, sorting, and processing of collected data. The collection comes packaged with Interfaces, classes, and algorithms.
The applications that are developed by inheriting the collection framework have access to these algorithms and use the already defined methods and procedures.
#2) Interfaces
Interfaces in Java provide the abstraction of the implementation i.e. using interfaces, the user is not aware of the details of the implementation, but can only see the methods and data required to write an application. The collection interface has many interfaces that can be implemented by the programmer to write their own classes.
#3) Classes
The classes of Collection Framework are data structures that can be implemented in a program. These classes implement the “Collection” interface and thus inherit all the methods and definitions of the collection interface.
A collection framework is used for storing and manipulating the collection that is the group of objects.
Java collection framework consists of high performing algorithms that carry out standard operations like searching, sorting and processing. It provides various standard implementations including LinkedList, TreeSet and HashSet for which interfaces are provided.
Next, let’s understand the Java Collection Hierarchy.
Java Collection Hierarchy
All the classes and interfaces shown in the below Java Collection hierarchy belong to “java.util.*” package.
As shown in the above diagram, the Java Collection Hierarchy consists of various classes and interfaces. As you can see, each of the class inherits from an interface and all the classes & interfaces, in turn, inherit from a single “collection” interface.
Let’s discuss some common methods in the collection interface along with a brief introduction about each of the classes and interfaces that are shown in the above hierarchy.
Collection Interface
The Collection interface is the root interface. All the classes in the collection framework implement the collection interface. This means every collection will have the methods declared in the Collection interface.
Some of the methods of the Collection interface are given below.
No | Method Prototype | Description |
---|---|---|
1 | public int size() | Returns the number of elements in a given collection. |
2 | public void clear() | Clears the collection by removing all the elements from the collection. |
3 | public boolean add(E e) | Inserts an element e in the collection. |
4 | public booleanaddAll(Collection< ?extends E> c) | Insert all the elements in the collection given by c into the collection. |
5 | public boolean remove(Object element) | Delete element given by ‘element’ from the collection. |
6 | public boolean removeAll(Collection< ?>c) | Remove the collection c from the collection. |
7 | default boolean removeIf(Predicate< ? super E> filter) | Remove all the elements that satisfy the given predicate ‘filter’ from the collection. |
8 | public booleanretainAll(Collection< ?> c) | Delete all elements from the collection except those in the specified collection c. |
9 | public Iterator iterator() | Return iterator for the collection. |
10 | public Object[] toArray() | Convert the collection into an array. |
11 | public < T> T[] toArray(T[] a) | Convert the collection into an array with a specified return type. |
12 | public boolean isEmpty() | Return if collection is empty or not. |
13 | public boolean contains(Object element) | Check if a collection contains the given element (Search operation). |
14 | public booleancontainsAll(Collection< ?>c) | Check if collection contains specified collection c inside it. |
15 | default Spliterator | Returns spliterator over a specified collection. |
16 | public booleanequals(Object element) | Used for matching two collections. |
17 | default Stream | Returns parallel stream using the collection as source. |
18 | default Stream | Returns sequential stream using the collection as source. |
19 | public int hashCode() | Returns numeric hashcode of the collection. |
Iterable Interface
The Iterable interface is also the base interface of the collection framework. The Collection interface that is the parent interface of all the other classes extends the Iterable interface. Hence all the classes implement a collection interface as well as an Iterable interface.
The Iterable interface has only one method iterator () that returns the iterator () that you can use to iterate over the elements of type T.
Iterator<T> iterator ()
Iterator Interface
The Iterator interface provides the ability to iterate over the elements in a forward direction.
The following are the methods that are supported by this interface.
No | Method Prototype | Description |
---|---|---|
1 | public Object next() | First returns the element and then moves the cursor to point to the next element. |
2 | public boolean hasNext() | Checks if the iterator has more elements. |
3 | public void remove() | Removes the element that is returned by the iterator in the end. |
List Interface
The list interface inherits the collection interface. List interface contains the data structures that are used to store ordered data or collection of objects. These data structures are of a list type. These data structures implementing the list interface may or may not have duplicate values.
List interface contains the methods that are used to access, insert or remove elements from the list-objects.
Various classes that implement the List interface are as follows:
- ArrayList
- LinkedList
- Vector
- Stack
We will discuss each of these classes briefly. Our subsequent topics will have a detailed discussion on each of the collection framework classes.
#1) ArrayList
ArrayList is the simplest implementation of the List interface. ArrayList preserves the insertion order and it is not synchronized.
The general definition of ArrayList data structure (Collection) is as follows:
List <data-type> list1= new ArrayList ();
Once the list is defined, you can use the ‘add’ method to add elements. Note that internally the ArrayList used dynamic array mechanism.
See the following examples that create an ArrayList collection of colors.
import java.util.*; class Main { public static void main(String args[]) { //Creating arraylist of String objects ArrayList<String> color_list=new ArrayList<String>(); //populate the arraylist with add method color_list.add("Red"); color_list.add("Green"); color_list.add("Blue"); color_list.add("Cyan"); color_list.add("Magenta"); color_list.add("Yellow"); //Traverse the list through Iterator Iterator itr=color_list.iterator(); System.out.println("The contents of the arraylist are:"); while(itr.hasNext()){ System.out.println(itr.next()); } } }
Output:
The above program shows the demonstration of the ArrayList collection. We add color values to the collection and then traverse the collection to display individual values in the collection using an iterator.
#2) LinkedList
LinkedList collection internally uses a doubly linked list mechanism for storing elements. It can contain duplicate elements. LinkedList collection operations are faster as shifting of elements is not required.
The general definition of creating a linked list is as follows:
List <data-type> list2 = new LinkedList ();
The following program demonstrates the linked list collection of number names.
import java.util.*; class Main { public static void main(String args[]) { //linked list of String objects LinkedList<String> linkedlist_num=new LinkedList<String>(); linkedlist_num.add("one"); linkedlist_num.add("two"); linkedlist_num.add("three"); linkedlist_num.add("four"); linkedlist_num.add("five"); //iterate over the linked list to display contents Iterator<String> itr=linkedlist_num.iterator(); System.out.println("The contents of the linked list are:"); while(itr.hasNext()) { System.out.println(itr.next()); } } }
Output:
Thus, we create a linked list and then add elements to it using the ‘add’ method. Then using an iterator, we traverse the linked list and display each element.
#3) Vector
Vector is similar to ArrayList and uses a dynamic array to store the elements like ArrayList. But vector supports many independent methods apart from the collection that makes it a better choice to be a preferred collection.
The general definition for vector collection is:
List <data-type> list3 = new Vector();
Note that although vector and ArrayList use the same mechanism of dynamic arrays, the vector elements are synchronized.
The Java program given below demonstrates the use of vectors in the collection framework.
import java.util.*; public class Main { public static void main(String args[]) { Vector<String> subject_vector=new Vector<String>(); subject_vector.add("English"); subject_vector.add("Hindi"); subject_vector.add("Maths"); subject_vector.add("Science"); Iterator<String> itr=subject_vector.iterator(); System.out.println("Vector contents:"); while(itr.hasNext()) { System.out.println(itr.next()); } } }
Output:
In this program, we have defined a vector collection consisting of subjects. We add various subjects and then use an iterator to output the elements.
#4) Stack
Stack data structure implements the last-in-first-out (LIFO) way of inserting elements. The stack is a subclass of the class vector (refer to the collection hierarchy diagram above). Apart from its own methods, the stack collection also supports the methods of vector collection.
The general definition of Stack collection is:
List <data-type> list4 = new Stack();
The following program implements Stack collection.
import java.util.*; public class Main { public static void main(String args[]) { Stack<Integer> even_stack = new Stack<Integer>(); even_stack.push(2); even_stack.push(4); even_stack.push(6); even_stack.push(8); even_stack.push(10); System.out.println("The element removed from stack: " + even_stack.pop()); Iterator<Integer> itr=even_stack.iterator(); System.out.println("The contents of the stack are:"); while(itr.hasNext()) { System.out.print(itr.next() + " "); } } }
Output:
As you can see in the above implementation, the new elements are added to the stack by using the ‘push’ operation. The stack has a single entry point called ‘Top of the stack’ and the elements are pushed onto the stack at the top. Thus, the last element added is at the top of the stack.
Like adding, elements are also removed from one end i.e. top of the stack. To remove elements, an operation ‘pop’ is used. Thus if you call pop (), the element at the top of the stack will be removed.
In the output above, we insert the element 2, 4, 6,8,10 and then call pop () so that 10 is removed.
Queue Interface
The collections derived from the queue interface follow the first-in-first-out(FIFO) order. The elements are inserted at one end and are removed from the other end. Hence the element entered first happens to be the element that is removed first.
Given below are the collections that support the query interface.
- PriorityQueue
- Deque Interface
- ArrayDeque
Let’s discuss each of these briefly.
#1) PriorityQueue
In PriorityQueue collection, the elements stored are processed based on their priorities. You cannot store null values in the priority queue.
The general definition of the priority queue is as follows:
Queue<data-type> q1 = new PriorityQueue();
The below program implements the priority queue.
import java.util.*; public class Main { public static void main(String args[]) { PriorityQueue<String> color_queue=new PriorityQueue<String>(); color_queue.add("red"); color_queue.add("green"); color_queue.add("blue"); color_queue.add("cyan"); color_queue.add("magenta"); color_queue.add("yellow"); System.out.println("Priority Queue elements:"); System.out.println("head:"+color_queue.peek()); System.out.println("Other elements in Priority Queue:"); Iterator itr=color_queue.iterator(); while(itr.hasNext()) { System.out.print(itr.next() + " "); } System.out.println("\n"); color_queue.remove(); System.out.println("After removing element, new head:"+color_queue.element()); System.out.println("\n"); color_queue.poll(); System.out.println("After removing another element, Priority Queue :"); Iterator<String> itr2=color_queue.iterator(); while(itr2.hasNext()) { System.out.print(itr2.next() + " "); } } }
Output:
Once again we use colors as elements of the priority queue. In the above program, we have used the methods add and remove to add elements to the queue and remove an element respectively. We use the peek () method that returns an element it points to in the priority queue.
Finally using an iterator, the elements of the priority queue are displayed.
#2) Deque Interface
Deque or a ‘double-ended queue’ is a data structure that allows you to add and remove the elements from both the ends. The deque interface in the Java collection framework that extends the Queue interface.
It provides the functionality of deque and has a class an ‘ArrayDeque’ inheriting from it.
#3) ArrayDeque
ArrayDeque implements the deque interface.
The general definition of ArrayDeque is as follows:
Deque<data_type> d = new ArrayDeque<data_type>();
ArrayDeque allows you to use the functionality of Deque. Unlike other collections like ArrayList or stack, ArrayDeque has no restrictions on its capacity.
The following example shows the implementation of ArrayDeque.
import java.util.*; public class Main { public static void main(String[] args) { //Creating Deque and adding elements Deque<Integer> deque = new ArrayDeque<Integer>(); deque.add(10); deque.add(20); deque.add(30); System.out.println("Deque Elements:"); //Traversing elements for (Integer num : deque) { System.out.println(num); } } }
Output:
In the above program, we define an ArrayDeque collection of type integer and add integer elements to it using the add method. The collection is then traversed using the for construct.
Set Interface
The set interface is a part of the java.util package and extends from the collection interface. Set is a structure that doesn’t allow the collection to have duplicate values and also more than one null value.
The following classes implement the set interface.
- HashSet
- LinkedHashSet
- TreeSet
#1) HashSet
HashSet collection that implements Set interface has distinct values stored in it. This collection uses the hashing technique to store the items and uses the hash table for storing elements.
The general definition of HashSet collection is shown below.
Set<data-type> s1 = new HashSet<data-type>();
We have given the HashSet implementation in the following program.
import java.util.*; public class Main { public static void main(String args[]) { //Create HashSet set_subjects HashSet<String> set_subjects=new HashSet<String>(); System.out.println("Elements in the given hashsetset_subjects are:"); set_subjects.add("Maths"); set_subjects.add("Computers"); set_subjects.add("English"); set_subjects.add("French"); //Traverse the hashset Iterator<String> itr=set_subjects.iterator(); while(itr.hasNext()) { System.out.println(itr.next()); } } }
Output:
In the above program, we create a HashSet collection of subjects and then traverse it using an iterator to display the elements in the collection.
#2) LinkedHashSet
LinkedHashSet implements a set interface and extends HashSet (refer collection hierarchy). LinkedHashSet is the linked list representation of the interface Set. LinkedHashSet contains unique elements but allows null values.
The general definition of LinkedHashSet is given below.
Set<data-type> s2 = new LinkedHashSet<data-type>();
The implementation for LinkedHashSet is given below.
import java.util.*; public class Main { public static void main(String args[]) { LinkedHashSet<String> set_subjects=new LinkedHashSet<String>(); System.out.println("Elements in the LinkedHashSet set_subjects:"); set_subjects.add("Maths"); set_subjects.add("Computers"); set_subjects.add("English"); set_subjects.add("Sanskrit"); Iterator<String> itr=set_subjects.iterator(); while(itr.hasNext()) { System.out.println(itr.next()); } } }
Output:
Once again we make use of book titles for creating Linkedhashset. As you can see from the output, the order of addition is maintained by linkedHashSet.
SortedSet Interface
SortedSet interface allows complete ordering of elements. It contains methods that provide a natural ordering of elements. Elements in the collection that implement the SortedSet interface are arranged in increasing order.
TreeSet class is one of the examples that implements the SortedSet interface.
Treeset
The general definition of Treeset is as follows:
Set<data-type> s3 = new TreeSet<data-type>();
TreeSet implements the SortedSet interface and contains unique elements. The storage and retrieval are quite fast and then the elements are arranged in ascending order.
import java.util.*; public class Main{ public static void main(String args[]) { //create a treeset of integers TreeSet<Integer> set_oddnums=new TreeSet<Integer>(); set_oddnums.add(1); set_oddnums.add(3); set_oddnums.add(5); set_oddnums.add(7); set_oddnums.add(9); System.out.println("Elements in TreeSet are:"); //traverse the treeset using iterator Iterator<Integer> itr=set_oddnums.iterator(); while(itr.hasNext()) { System.out.print(itr.next() + " "); } } }
Output:
In the above program, we created and added odd numbers to the collection using add methods. Then using an iterator, we output the elements in the collection.
Advantages Of Java Collections Framework
- Reduced programming: The Collections framework comes with all the interfaces and classes containing the methods that can allow programmers to write an efficient program. This way, the programmer need not focus on too much programming.
- Consistent methods and API: All the classes have common methods that act on data. These APIs are consistent throughout the classes and the programmer need not worry about having too many different methods for each class.
- Increase speed and accuracy: You can write highly efficient programs using a collection framework and also faster & accurate programs as the collection framework provides the full functionality to implement the data structures and collections.
- Facilitates software reuse: Data structures and algorithms of the Java collection framework are reusable.
- Interoperability among unrelated APIs: Collection APIs allow interoperability even among unrelated APIs.
- Fewer efforts to design new APIs: Programmers can use the standard collection APIs and design new APIs based on that. They don’t have to struggle to write complete new APIs.
Frequently Asked Questions
#1) What is the use of a collection framework in Java?
Answer: Collection framework offers prepackaged algorithms, interfaces, and classes that allow programmers to write highly efficient programs that can store and process data.
#2) Why Collection is a framework?
Answer: A framework is a reusable collection of classes, interfaces, and algorithms. The collection framework also is a reusable collection of data structure classes and algorithms operating on these classes.
#3) What is Java Collections API in Java?
Answer: The Java collections API provides interfaces and classes that can be extended and implemented in order to use data structures that are nothing but collections.
#4) What is the difference between collection and collections in Java?
Answer: The collection is a base interface in the collection framework while ‘collections’ is a class. Both are a part of java.util package.
****More details and examples of the Java Collections Framework:****
Comparison between List, Set, and Queue:
List | Set | Queue |
---|---|---|
Insertion order is maintained | Insertion order is not maintained in Hash set | Insertion order is maintained. |
Can contain duplicate elements | Cannot contain duplicate elements | Can contain duplicate elements. |
Insertion and removing of array can be done for any index. | Remove the specified element. | Only the last inserted element can be popped out. Also, insertion of elements happens at end. |
Array List Class
In Array, the memory allocation is fixed. But in ArrayList, memory can be allocated dynamically. This ArrayList class maintains the insertion order and you can insert duplicate elements.
Demo program for Array List:
public class ArrayListDemo { public static void main(String[] args) { ArrayList li = new ArrayList (); li.add(1); li.add(2); li.add(3); li.remove(0); for (Integer temp : li) { System.out.println(temp); } System.out.println("=========="); ArrayList l = new ArrayList(); l.add("text1"); l.add("text2"); l.add("text3"); for (String temp : l) { System.out.println(temp); } System.out.println("=========="); ArrayList al=new ArrayList(); al.add(1); al.add(2); al.forEach((a)->;System.out.println(a)); } }
LinkedList Class
Linked List data structure contains nodes and this node will contain two parts:
- Data
- Reference to the next element
The first node is not a separate node. It contains only the reference and is called a head. The last node is null.
Demo Program:
public class LinkedListDemo { public static void main(String[] args) { LinkedList list =new LinkedList(); list.add(22); list.add(44); list.add(46); list.add(46); list.add(46); for(Integer temp:list) { System.out.println(temp); } Iterator it =list.iterator(); while(it.hasNext()) { System.out.println(it.next()); } System.out.println("=========="); for (int i=0;i<list.size();i++) { System.out.println(list.get(i)); } } }
Queue
A queue is first in first out (FIFO) data structure. If you call the remove method, always the first inserted element will be removed from the queue. So, Queue is used in real time application where the data has to be retrieved in the inserted order.
Example Program:
public class QueueDemo { public static void main(String[] args) { PriorityQueue pq=new PriorityQueue(); pq.add(1); pq.add(2); pq.add(3); pq.add(4); pq.add(5); pq.add(6); pq.add(7); for(int temp : pq) { System.out.println(temp); } pq.remove(); System.out.println("queue after removing a element"); System.out.println(pq); } }
Set
A set collection will not allow duplicate elements. You can use a set data structure, when you want to process the collection of data without duplication, and when there is no need to maintain the insertion order.
Demo Program:
public class demohashset { public static void main (String[] args){ HashSet hs=new HashSet(); hs.add(23); hs.add(24); hs.add(25); hs.add(26); hs.add(27); hs.add(28); hs.add(293); hs.add(203); hs.add(263); hs.add(243); hs.add(243); (int temp:hs) { System.out.println(temp); } hs.remove(24); hs.remove(23); System.out.println("==============="); System.out.println("after removing a element ::::"); System.out.println("==============="); hs.forEach((temp)->System.out.println(temp)); ; } }
MAP Interface
- When you want process collection of elements with the key and value pair, then you can use map data structure as the map is an object which can map keys to values.
- A map cannot contain duplicate keys.
- The important implementations of map are HashMap, Treemap, LinkedHashMap, HashTable.
Difference between HashMap, Treemap, LinkedHashMap, and HashTable:
HashMap | TreeMap | LinkedHashmap | HashTable |
---|---|---|---|
Null keys and values are allowed | Only null values allowed. | Null keys and values allowed. | It won’t allow null keys and values. |
Not synchronized | Not synchronized | Not synchronized | synchronized |
There is no guarantee to maintain order in the iteration | Sorting will be done based on natural order. | Insertion order will be maintained | Insertion order not maintained. |
Demo Program:
public class HashMapDemo { public static void main(String[] args) { HashMap<Integer, String> m=new HashMap<Integer,String>(); m.put(1, "one"); m.put(2, "two"); m.put(3, "three"); m.put(4, "four"); m.put(null, "one"); m.put(null, null); System.out.println(m); TreeMap<String, String> tm =new TreeMap<String, String>(); tm.put("R", "red"); tm.put("B", null); tm.put("G", "green"); System.out.println(tm); Hashtable<Integer, String> ht =new Hashtable<Integer, String>(); ht.put(1, "one"); ht.put(2, "two"); ht.put(3, "three"); ht.put(4, "four"); System.out.println(ht); } }
Key Points to be noted:
- List, Queue, set interfaces extend the collection interface and this collection interface have common methods like add, remove etc.
- Insertion order is maintained in list and a set cannot contain duplicate elements. Queue is First in First out data structure.
- Map will contain key and value pairs. HashMap, Treemap, Hashtable, Linked HashMap are the important implementation of the map interface.
Conclusion
This tutorial gave us an introduction to the Java Collections Framework. We briefly touched all the classes and interfaces that are a part of the Java collection framework.
In our subsequent tutorials in this series, we will learn in detail about each of these classes and interfaces.
You can explore more about Reflections in JAVA in our upcoming tutorial!!!