Content to be covered:
- Introduction of Collection Framework
- Need for Collection Framework (with Example)
- Problems with Array
- Advantages of using the Collection Framework
- Java Collection Hierarchy (Interfaces & Classes)
- Collection Interfaces
- Java List: ArrayList, LinkedList, Vector
- Java Set: HashSet, LinkedHashSet, TreeSet
- Java Deque: ArrayDeque, LinkedList
- Iterators in Java Collections
- Java Generics
Watch this video for a hands-on explanation and deeper insights:
Chapters (Clickable):
- Introduction
- Need of Collection Framework (with Example)
- Advantages of using Collection Framework
- Java Collection Hierarchy (Interfaces & Classes)
- Collection Interfaces
- Introduction of List Interface in Java
- Introduction of Set Interface in Java
- Introduction of Deque Interface in Java
- Introduction of Queue Interface in Java
- Java List: ArrayList, LinkedList, Vector
- Java Set: HashSet, LinkedHashSet, TreeSet
- Java Deque: ArrayDeque, LinkedList
- Iterators in Java Collection
- Java Generics
- Q&A Discussion
1. Java Generics:
Java Generics is a feature that allows you to write type-safe and reusable code by allowing classes, interfaces, and methods to operate on objects of various types while providing compile-time type checking. There are many advantages of using Java Generics:
i. Elimination of casts.
The following code snippet, without generics which requires casting:
List list = new ArrayList();
list.add("hello");
String s = (String) list.get(0);
When rewritten to use generics, the code does not require casting:
List<String> list = new ArrayList<String>();
list.add("hello");
String s = list.get(0); // no cast
ii. We can decide on the object type later
class SampleClass {
public static void main(String[] args) {
Test<Integer> obj1 = new Test<Integer>(10);
System.out.println(obj1.getObject());
Test<String> obj2 = new Test<String>("AkashChauhan");
System.out.println(obj2.getObject());
}
}
//We use <T> to specify Parameter type
class Test<T> {
// An object of type T is declared
T a;
// constructor
Test(T b) {
this.a = b;
}
T getObject() {
return this.a;
}
}
2. Java Collection Framework:
Questions to think about:
- Why do we need a collection, or what is the purpose of using collection interfaces?
- Why this order, Individual {1st level}->Arrays {2nd level}->Collection {3rd level}, is important?
- What are the disadvantages of creating Individual Elements?
- What are the advantages of an Array?
- What are the disadvantages of an Array?
- What are the advantages of using collection interfaces?
- What are List, Set, and Queue interfaces?
- What are the different types of implementation classes of the above interfaces?
What are the needs and advantages of using the Collection Framework?
1. When using Individual Element {Problems-1}
- When creating 10000 variables, it is not good practice to create 1000 different individual variables
- So array comes into the picture. An array can represent many values using a single variable.
2. When using Array {Problems-2}
- Fix in Size -> It is compulsory to provide the size during compilation, or before using it.
- Only Homogeneous -> Holds only homogeneous data type elements
- We are always responsible for making our methods {Array is not based on some standard data structure, so readymade methods support is not there}
3. When using Collection {Benefits, to overcome above problems}
- Growable in nature -> Not bound to fix the size at the start
- Homogeneous + Hetrogeneoud {$Hetrogeneous Objects Collection}
- Can use the Readymade methods from the standard DS
public class SampleClass {
@SuppressWarnings({ "unchecked", "rawtypes" })
public static void main(String[] args) {
ArrayList al = new ArrayList();
al.add(1);
al.add("abc");
al.add(new String("def"));
System.out.println(al);
}
}
- A Collection represents a single unit of objects.
- The Collection interface (java.util.Collection) and Map interface (java.util.Map) are the two main “root” interfaces of Java collection classes.
- Java Collections can achieve all the operations you perform on data, such as searching, sorting, insertion, manipulation, and deletion, without writing boilerplate code.
- It provides readymade architecture/Classes/methods.
What are the different Java Collection interfaces and Classes available in Java?
It is a collection of collection classes and map classes. It is also called the Java Collection Framework.
1. Collection Interface (Their Implementation Classes)
2. Map Interface (Their Implementation Classes)

All these interfaces like list, set, queue and dequeu extend collection interface, that’s why they are called main components of collection framework.
1. Collection Interfaces:
- List<T>
- Set<T>
- Queue<T>
- Deque<T>
S.No | Interface | Description |
1 | List<T> | . It is an ordered collection of objects. . In which duplicate values can be stored. . Multiple Null Values are allowed. |
2 | Set<T> | . It is an unordered collection of objects. . In which duplicate values cannot be stored, at most one null value. |
3 | Queue<T> | . Ordered, FIFO, Allows duplicates, Allows multiple null values. . Insertion of an element from the end and deletion from the beginning. |
4 | Deque<T> | . It is also known as Array Double Ended Queue or Array Deck. . Elements can be inserted and deleted from both of the ends. |
1.1 List<T> Interface and its implementation classes:
- ArrayList<T>, LinkedList<T>, Stack<T> and Vector<T> are the four implementation classes of List<T> interface
- ArrayList<T> and LinkedList<T> are mainly used
S.No | Implementation Classes | Description |
1 | ArrayList<T> | . The ArrayList class is a re-sizable array. . In ArrayList accessing an element takes constant time O(1) {Fast random access} and adding an element takes O(n) time in the worst case(adding an item at the first position). . Adding elements in between would cost more space, as shifting the rest of the elements would take place. |
2 | LinkedList<T> | . LinkedList adding an element takes O(n) time(at the end of the list) and accessing also takes O(n) time. . LinkedList uses more memory than ArrayList because of extra overhead for the next and previous pointers for each node in the linked list. . It is not synchronized. |
1. Code for ArrayList<T>
public class SampleClass {
public static void main(String[] args) {
List<Integer> l1 = new ArrayList<Integer>();
l1.add(0, 1);
l1.add(1, 2);
l1.add(2, 2);
l1.add(3, null);
l1.add(4, null);
System.out.println(l1);
// Creating another list
List<Integer> l2 = new ArrayList<Integer>();
l2.add(3);
l2.add(4);
l2.add(5);
// Will add list l2 from 5 index
l1.addAll(5, l2);
System.out.println(l1);
// Removes element from index 1
l1.remove(2);
System.out.println(l1);
// Print element at index 3
System.out.println(l1.get(3));
// Replace 0th element with 5
l1.set(0, 5);
System.out.println(l1);
}
}
2. Code for LinkedList<T>
public class SampleClass {
public static void main(String[] args) {
// Creating a list
List<Integer> l1 = new LinkedList<Integer>();
l1.add(0, 1);
l1.add(1, 2);
System.out.println(l1);
// Creating another list
List<Integer> l2 = new LinkedList<Integer>();
l2.add(1);
l2.add(2);
l2.add(3);
// Will add list l2 from 1 index
l1.addAll(1, l2);
System.out.println(l1);
// Removes element from index 1
l1.remove(1);
System.out.println(l1); // [1, 2, 3, 2]
// Prints element at index 3
System.out.println(l1.get(3));
// Replace 0th element with 5
l1.set(0, 5);
System.out.println(l1);
}
}
1.2 Set<T> Interface and its implementation classes:
- HashSet<T>, LinkedHashSet<T>, and TreeSet<T> are implementation classes of the Set<T> interface.
- HashSet<T> and LinkedHashSet<T> are mainly used.
S.No | Implementation Classes | Description |
1 | HashSet<T> | . It uses HashMap. . It does not guarantee that the Insertion order will remain constant over time. |
2 | LinkedHashSet<T> | . It uses a doubly-linked list. . Preserve insertion order. |
1. Code for HashSet<E>
public class SampleClass {
public static void main(String[] args) {
Set<String> hash_Set = new HashSet<String>();
hash_Set.add("Amit");
hash_Set.add("For");
hash_Set.add("Amit");
hash_Set.add("Example");
hash_Set.add("Set");
hash_Set.add(null);
hash_Set.add(null);/* It would not make sense, as at most one null element is allowed */
System.out.println("Set output without the duplicates");
System.out.println(hash_Set);
hash_Set.remove(null);
System.out.println("\nSorted Set after passing into TreeSet");
Set<String> tree_Set = new TreeSet<String>(hash_Set);
System.out.println(tree_Set);
}
}
2. Code for LinkedHashSet<E>
public class SampleClass {
public static void main(String[] args) {
Set<String> hash_Set = new LinkedHashSet<String>();
hash_Set.add("Amit");
hash_Set.add("For");
hash_Set.add("Amit");
hash_Set.add("Example");
hash_Set.add("Set");
hash_Set.add(null);
hash_Set.add(null);/* It would not make sense, as at most one null element is allowed */
System.out.println("Set output without the duplicates");
System.out.println(hash_Set);
hash_Set.remove(null);
System.out.println("\nSorted Set after passing into TreeSet");
Set<String> tree_Set = new TreeSet<String>(hash_Set);
System.out.println(tree_Set);
}
}
1.3 Queue<T> Interface and its implementation classes:
- PriorityQueue<T>, LinkedList<T>, PriorityBlockingQueue<T> and LinkedBlockingQueue<E> are four implementation classes of Queue interface.
- PriorityQueue<T> and LinkedList<T> are mainly used implementation classes of the queue.
S.No | Implementation Classes | Description |
1 | PriorityQueue<T> | . Order not preserved, allows duplicates, no null values, not thread-safe. . It does not follow the FIFO order and store elements based on their priority. . Priorities can be set using the ‘Comparable Interface’ and its compareTo() method. |
2 | LinkedList<T> | . Not thread-safe, Allows duplicates, Allows multiple null values, preserved order |
1. Code for PriorityQueue<T>
public class SampleClass {
public static void main(String[] args) {
Queue<Integer> q = new PriorityQueue<Integer>();
// Adds elements {0, 1, 2, 3, 4} to queue
for (int i = 0; i < 5; i++)
q.add(i);
q.add(2);
// Display contents of the queue.
System.out.println("Elements of queue-" + q);
// To remove the head of queue.
int removedEle = q.remove();
System.out.println("removed element-" + removedEle);
System.out.println(q);
// To view the head of queue
int head = q.peek();
System.out.println("head of queue-" + head);
//Size of the queue
int size = q.size();
System.out.println("Size of queue-" + size);
}
}
2. Code for LinkedList<T>
public class SampleClass {
public static void main(String[] args) {
Queue<Integer> q = new LinkedList<Integer>();
// Adds elements {0, 1, 2, 3, 4} to queue
for (int i = 0; i < 5; i++)
q.add(i);
q.add(2);
// Display contents of the queue.
System.out.println("Elements of queue-" + q);
// To remove the head of queue.
int removedEle = q.remove();
System.out.println("removed element-" + removedEle);
System.out.println(q);
// To view the head of queue
int head = q.peek();
System.out.println("head of queue-" + head);
// Size of the queue
int size = q.size();
System.out.println("Size of queue-" + size);
}
}
1.4 Deque<T> Interface and its implementation classes:
- ArrayDeque<T> and LinkedList<T> are the two main implementation classes of the deque interface.
- ArrayDeque<T> is the deque interface’s main implementation class.
S.No | Implementation Classes | Description |
1 | ArrayDeque<T> | . Faster than linked list due to the array-based implementation . not thread-safe (not synchronized) . can not contain null values. . follow contagious memory allocation |
2 | LinkedList<T> | . Uses a doubly-linked list as its internal data structure. . can contain null values . extra memory overhead due to previous and next pointer . it is also not thread-safe |
1. Code for ArrayDeque<T>
public class DequeueUsingArrayDequeue {
public static void main(String[] args) {
Deque<Integer> de_que = new ArrayDeque<Integer>();
//By Default FIFO order
de_que.add(10);
de_que.add(20);
de_que.add(30);
de_que.add(40);
de_que.add(50);
for (Integer element : de_que) {
System.out.print(element);
System.out.print(",");
}
System.out.print("\n");
// Clearing all elements using clear() method
de_que.clear();
//
// Inserting at the start
de_que.addFirst(564);
de_que.addFirst(291);
// Inserting at end
de_que.addLast(24);
de_que.addLast(14);
for (Iterator itr = de_que.iterator(); itr.hasNext();) {
System.out.println(itr.next());
}
}
}
What is an iterator in Java?
In Java, an Iterator is an object used to traverse (iterate over) elements in a Collection (like ArrayList
, HashSet
, etc.) one at a time.
1. Defined in java.util
package.
2. Provides three main methods:
. remove()
– removes the last element returned by next()
(optional).
. hasNext()
– returns true
If there are more elements to iterate.
. next()
– returns the next element.
import java.util.*;
public class IteratorExample {
public static void main(String[] args) {
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
Iterator<String> iterator = names.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
Questions for Practice/Assignment:
Do your best to solve and answer these questions using your current knowledge. If you’re not confident in a concept, take the time to learn it first, then attempt to solve and answer the questions.
Q1. What is the Java Collection Framework?
Q2. What are the main interfaces of the Collection Framework?
Q3. What are all the interfaces and implementation classes in the Collection Framework? Construct a tree containing all such interfaces and classes.
Q4. What are the main differences between List and Set in Java? Explain all possible points of comparison and specify the scenarios in which one should prefer using a List over a Set, and vice versa?
Q5. Explain all possible points of comparison and specify the scenarios in which one should prefer using ArrayList over LinkedList, and vise versa?
Q6. Explain all possible points of comparison and specify the scenarios in which one should prefer using HashSet over LinkedHashSet, and vise versa?
Q7. What are the main differences between Queue and Deque in Java? Explain all possible points of comparison and specify the scenarios in which one should prefer using a Queue over a Deque, and vice versa?
Q8. Explain all possible points of comparison and specify the scenarios in which one should prefer using PriorityQueue over LinkedList, and vise versa?
Q9. What is an Iterator in Java, and how does it differ from a ListIterator? Explain their key differences and typical use cases. Also, write a Java program to:
- Take a list of integers as input.
- Print all the elements in the forward direction using
Iterator
. - Reverse the list using
ListIterator
and print it.
Q10. What are the advantages of using Java Generics? Explain it through an example.
- Design a generic class named Pair that can hold a pair of values of any two types. The class should accept two type parameters, T and U, and store two fields accordingly. Include a constructor to initialize these fields and provide public getter methods getFirst(), and
getSecond()
to access the values. This exercise reinforces the concept of generic classes in Java and demonstrates how generics improve code reusability and type safety.
Q11. Why would you choose TreeSet over HashSet in Java? Explain the use cases and differences that justify using TreeSet.
Q12. What is the difference between peek(), poll(), and remove() in the Queue?
Q13. Find duplicates in an ArrayList without using a Set.
Input: List nums = [1, 2, 3, 4, 2, 5]
Q14. Check if a list is a palindrome.
Input: List list = [‘a’, ‘b’, ‘c’, ‘b’, ‘a’]
Output: true (The list is a palindrome.)
Q15. Rotate a list to the right by k steps.
Input: List list = [1, 2, 3, 4, 5], k = 2
Output: [4, 5, 1, 2, 3] (List after rotating 2 steps to the right.)
Q16. Reverse the first k elements of a queue.
Input: Queue queue = [1, 2, 3, 4, 5], k = 3
Output: [3, 2, 1, 4, 5] (First k elements are reversed in the queue.)
Q17. Check if a string has all unique characters using a Set.
Input: “abcdef”
Output: true (All characters are unique.)
Q18. Remove all elements from one set that are present in another set.
Input: set1 = {1, 2, 3, 4}, set2 = {2, 3}
Output: set1 = {1, 4} (Remove all elements from set1 that are in set2.)
Q19. Merge two sorted lists into one sorted list.
Input: List list1 = [1, 3, 5], list2 = [2, 4, 6]
Output: [1, 2, 3, 4, 5, 6] (Merged sorted list.)
Q20. Find the first non-repeating element in a list.
Input: List nums = [4, 5, 1, 2, 5, 1, 4, 7]
Output: 2 (The first non-repeating element.)
Live Discussion with Code Examples (Revision and Q&A Session)
Thanks and Regards
Thank You Akash Sir. Your free notes are very helpful they are straight on-point and easy to understand also I love your Youtube Playlist on Java..
Thank you so much for your feedback! I’m delighted to hear that you find the notes helpful and easy to understand. I’m also glad that you’re enjoying the YouTube playlist on Java. Your appreciation motivates me to keep creating more valuable content.