What is Collection in Java?
A collection in java is represented as a container that groups all the elements into a single unit. For example, a mail folder (group of emails), a telephone directory (mapping of names to phone numbers).What is a Framework?
A framework is a basic foundation or layout on which you start working by using the different classes and interfaces provided. For example, Laravel is one of the most famous PHP frameworks that provides a basic skeleton for your application.What is the Collections Framework in Java?
All objects are grouped into a single object along with an architecture that represents and provides different methods for manipulating collections. So Collections framework in Java provides different data structures already implemented for storing data and methods, to manipulate them with features such as sorting, searching, deletion, and insertion. For example, you want to implement a system for some random company to improve service for their customers, based on the first come first serve basis. This is also known as a FIFO (first in first out) implementation. Now we need to implement this data structure and then use it to achieve our goal. The Collections framework provides us with a Queue interface which we only need to import rather than implement, then use it, and we are done. Implementation: You can import all of the collections by using the following line:import java.util.*;
If you want to import a specific collection then use the exact package name, such as:
import java.util.LinkedList;
Benefits of Collections Framework in Java
It has the following benefits.- Already Implemented (time-saving).
- Performance Efficiency (speed and quality).
- Reduces effort to learn and use new APIs.
What’s the Hierarchy of Collection Framework?
Now let's see the collections hierarchy but first, we need to know the essential components of this framework.- Interfaces
- Classes (implementation)
- Algorithms
Hierarchy of Collection Framework
For your understanding:- Collection, Set, Queue, and List all are interfaces. Set, Queue and List are extended by the Collection interface.
- PriorityQueue, HashSet, LinkedList, and Stack all are classes or the implementation of these interfaces.
- It is not mandatory that a class implements just one interface. LinkedList also implements the Deque interface, for example.
Types Of Collections
Java collections framework has a lot of types of collections in it to reduce our efforts. Here is a list of some of the collections:- ArrayList Class
- LinkedList Class
- List Interface
- Set Interface
- Queue Interface
- Map Interface
- PriorityQueue Class
- HashMap Class
- Comparable Interface
- LinkedHashMap Class
- TreeMap Class
- HashTable
Collection Interfaces
Here we will discuss some common collection interfaces and then some methods implemented by the classes.Collection Interface
This is a basic foundation for the Collections framework as it provides all the necessary methods for implementation. The Map is the only data structure that does not implement it but the remaining all implement its methods. This interface has methods for knowing the size of the collection, and whether an object exists in the collection, adding or removing objects from the collection.Iterable Interface
It is the root interface for the Collections framework as it is extended by the Collection interface which is implemented by all classes. It returns an iterator for the specific collection to iterate over it.Queue Interface
Queue is used to hold the elements but they can not be processed. Implementing the basic collection operations, it also provides additional insertion and extraction methods.Set Interface
Set is used to hold unique elements in it. It never contains duplicate elements and models the mathematical set abstraction to represent the sets such as processes running on a machine.List Interface
List is an ordered collection sometimes called a sequence which can hold duplicate elements in it. It provides control to the user for updating or removing a specific element, inserting an element at a specific point by using its integer index value. LinkedList and ArrayList are implementation classes of the List interface.Deque Interface
Deque stands for the double-ended queue which means that we can perform operations on both ends. We can insert and remove elements from both ends. The Deque interface extends the queue interface. ArrayDeque and LinkedList both implement the Deque interface. It provides methods for insertion, deletion, and examining the instance from both ends.Map Interface
Map interface is also part of the Collections framework but it does not extend the Collection interface. It is used to store key-value pairs. Its main implementations are HashMap, TreeMap, and LinkesHashMap which are similar in certain aspects to HashSet, TreeSet, and LinkedHashSet. It always contains unique keys but the values can be duplicated. It is useful when you need to add, delete, or search for an item based on a key. It provides us with basic methods such as put, get, remove, size, empty, and so on.Common Methods of these Interfaces
Now we will look at some common methods provided for the implementation of different classes in this framework except the Map interface.Methods | Description |
---|---|
public boolean add(E e) | Used to insert an element into the collection |
public boolean remove(Object element) | Used to remove an element from the collection |
public int size() | Returns the number of elements in a collection |
public boolean contains(Object element) | Used to search for an element |
public boolean isEmpty() | Checks if the collection is empty |
public boolean equals(Object element) | Checks for equality |
Collection Classes
As we know the framework has different interfaces which are implemented by many classes inside it. Now let's have a look at some commonly used classes.LinkedList
It is the most commonly used data structure that implements a doubly linked list to store the elements inside it. It can store duplicate elements. It implements the Dequeue interface extended by the Queue interface and the List interface. It is not synchronized. Now let’s see how to solve our problem discussed above (the FIFO concept) using LinkedList. The problem is to serve the customers in a manner they arrive i.e first in first out.Example
import java.util.*;
public class LinkedListExample {
public static void main(String[] args) {
Queue<String> customerQueue = new LinkedList<String>();
//Adding customers to the Queue as they arrived
customerQueue.add("John");
customerQueue.add("Angelina");
customerQueue.add("Brooke");
customerQueue.add("Maxwell");
System.out.println("Customers in Queue:"+customerQueue);
//element() => returns head of the queue
//we will see our first customer and serve him
System.out.println("Head of the queue i.e first customer: "+customerQueue.element());
//remove () method =>removes first element(customer) from the queue i.e the customer is served so remove him to see next
System.out.println("Element removed from the queue: "+customerQueue.remove());
//poll () => removes and returns the head
System.out.println("Poll():Returned Head of the queue: "+customerQueue.poll());
//print the remaining customers in the Queue
System.out.println("Final Queue:"+customerQueue);
}
}
Output
Customers in Queue:[John, Angelina, Brooke, Maxwell]
Head of the queue i.e first customer: John
Element removed from the queue: John
Poll():Returned Head of the queue: Angelina
Final Queue:[Brooke, Maxwell]
ArrayList
It simply implements the List interface. It maintains the insertion order and uses a dynamic array to store elements of different data types. Elements can be duplicated. It is also non-synchronized and can store null values. Now let’s see its different methods... These are useful when we do not know how many records or elements we need to insert. Let’s take an example of a library where we don’t know how many books we have to keep. So whenever we have a book, we need to insert it into ArrayList.Example
public class ArrayListExample {
public static void main(String args[]) {
// Creating the ArrayList
ArrayList<String> books = new ArrayList<String>();
// Adding a book to the list
books.add("Absalom, Absalom!");
// Adding a book in array list
books.add("A Time to Kill");
// Adding a book to the list
books.add("The House of Mirth");
// Adding a book to the list
books.add("East of Eden");
// Traversing the list through Iterator
Iterator<String> itr = books.iterator();
while (itr.hasNext()) {
System.out.println(itr.next());
}
}
}
Output
Absalom, Absalom!
A Time to Kill
The House of Mirth
East of Eden
HashSet
It implements the Set interface and never contains duplicate values. It implements the hash table for storing the values. It also allows null values. It never maintains the insertion order but provides the constant time performance for add, remove, size, and contains methods. It is best for search operations and it is not synchronized.Example
import java.util.*;
class HashSetExample{
public static void main(String args[]){
//creating HashSet and adding elements to it
HashSet<Integer> hashSet=new HashSet();
hashSet.add(1);
hashSet.add(5);
hashSet.add(4);
hashSet.add(3);
hashSet.add(2);
//getting an iterator for the collection
Iterator<Integer> i=hashSet.iterator();
//iterating over the value
while(i.hasNext()) {
System.out.println(i.next());
}
}
}
Output
1
2
3
4
5
As you can see it does not maintains the insertion order.
ArrayDeque
It implements the Deque interface so it allows operations from both ends. It does not allow null values. It is faster than Stack and LinkedList when implemented as Stack and LinkedList. ArrayDeque has no size restrictions as it grows and shrinks as per the requirements. It is unsynchronized, meaning it is not thread-safe. To keep it thread-safe we have to implement some external logic.Example
import java.util.*;
public class ArrayDequeExample {
public static void main(String[] args) {
//creating Deque and adding elements
Deque<String> deque = new ArrayDeque<String>();
//adding an element
deque.add("One");
//adding an element at the start
deque.addFirst("Two");
//adding an element at the end
deque.addLast("Three");
//traversing elements of the collection
for (String str : deque) {
System.out.println(str);
}
}
}
Output
Two
One
Three
HashMap
It is the implementation of the Map interface backed by the hash table. It stores the key-value pairs. It does not allow null values. It is not synchronized. It never guarantees the insertion order. It provides constant time performance for methods like get, and put. Its performance depends on two factors — initial capacity and load factor. Capacity is the number of buckets in the hash table so the initial capacity is the number of buckets allocated at the time of creation. Load factor is the measure of how much a hash table can be populated before its capacity is increased. The rehash method is used to increase the capacity and it mainly doubles the number of buckets.Example
import java.util.*;
public class HashMapExample{
public static void main(String args[]){
//creating a HashMap
HashMap<Integer,String> map=new HashMap<Integer,String>();
//putting elements into the map
map.put(1,"England");
map.put(2,"USA");
map.put(3,"China");
//get element at index 2
System.out.println("Value at index 2 is: "+map.get(2));
System.out.println("iterating map");
//iterating the map
for(Map.Entry m : map.entrySet()){
System.out.println(m.getKey()+" "+m.getValue());
}
}
}
Output
Value at index 2 is: China
iterating map
1 England
2 USA
3 China
Algorithms
The Collections framework provides us with different algorithms for different operations to apply to the collections. Here we will look at which major operations are covered by these algorithms. It contains algorithms related to:- Sorting
- Searching
- Shuffling
- Routine Data Manipulation
- Composition
- Finding Extreme Values
Sorting
The sort algorithm reorders a list according to an ordering relationship. Two forms of relationships are provided.- Natural Ordering
- Comparison Ordering
Natural Ordering
In natural ordering a list is sorted according to its elements.Comparison Ordering
In this form of ordering an additional parameter, which is a comparator, is passed along with the list. A slightly optimized merge sort algorithm is used for sorting which is fast and stable as it guarantees the n log(n) running time and it does not reorder equal elements. We will be using the same example from ArrayList to demonstrate the sorting.Example
import java.util.*;
public class SortingExample{
public static void main(String args[]){
//Creating arraylist
ArrayList<String> books=new ArrayList<String>();
//Adding a book to the arraylist
books.add("A Time to Kill");
//Adding a book to the arraylist
books.add("Absalom, Absalom!");
//Adding a book to the arraylist
books.add("The House of Mirth");
//Adding a book to the arraylist
books.add("East of Eden");
//Traversing list through Iterator before sorting
Iterator itrBeforeSort=books.iterator();
while(itrBeforeSort.hasNext()){
System.out.println(itrBeforeSort.next());
}
//sorting the books
Collections.sort(books);
System.out.println("After sorting the books");
//Traversing list through Iterator after sorting
Iterator itr=books.iterator();
while(itr.hasNext()){
System.out.println(itr.next());
}
}
}
Output
A Time to Kill
Absalom, Absalom!
The House of Mirth
East of Eden
After sorting the books
A Time to Kill
Absalom, Absalom!
East of Eden
The House of Mirth