Que What is Java Collection Framework?
Ans Java Collection framework is a powerful built-in library that provides set of optimised implementaions of most commonly used data structures and algorithms.It is widely utilized in building Java applications and solving real-world software development challenges.
Que Advantages of Java Collection Framework?
Ans Some of the advantages of Java Collection framework are
- Unified Architecture : Every data structure is derived from interfaces such as iterable interface and collection interface providing a sense of common implementations.
- Ease of use : It simplifies the development process by providing pre-built data structures and algorithms. The developer can focus more on business logic rather than manually implementing and optimising commonly used data structures and standard algorithms.
- Flexibility : If we want to change underlying data structures, we can do it easily without worrying that changing data structure will change data retrieval and access patterns(mostly).
- Thread Safety : As java provides a way to run processes on different threads individually, Java Collection Framework provides different classes to run in multithread envorinments and single threaded applications.
JAVA COLLECTION FRAMEWORK HIERARCHY
ITERABLE INTERFACE
The Iterable interface in Java is a key component of the Collection Framework. It is the root interface for all collection types that can be iterated over. Implementing the Iterable interface allows an object to be the target of a "for-each loop" (also known as the enhanced for loop).
Also it provides a iterator object that can be used for forward iteration of all data structures that implements this iterable interface.
Example using FOR EACH LOOP (ENHANCED FOR LOOP)
Internally ArrayList implements List and List Interface extends Collection Interface and Collection Interface extends Iterable Interface.
List<String> list = new ArrayList<>();//Declaring a Data Structure
list.add("Java");//Add element
list.add("Collections");//Add element
list.add("Framework");//Add element
for (String element : list) {//Iterating using enhanced for loop
System.out.println(element);
}
Example using ITERABLE Object
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
String element = iterator.next();
System.out.println(element);
}
So we can create custom iterable implementing iterable interface and overriding next,hasNext and remove method. Here is example of the same.
import java.util.Iterator;
class CustomIterable implements Iterable<Integer> {
private final int[] numbers = {1, 2, 3, 4, 5};
@Override
public Iterator<Integer> iterator() {
return new Iterator<Integer>() {
private int index = 0;
private int lastReturnedIndex = -1;
@Override
public boolean hasNext() {
return index < numbers.length;
}
@Override
public Integer next() {
if (!hasNext()) {
throw new java.util.NoSuchElementException();
}
lastReturnedIndex = index;
return numbers[index++];
}
@Override
public void remove() {
// This example uses an array, so removal is not supported.
throw new UnsupportedOperationException("Remove operation is not supported.");
}
};
Note :
- Iterators in Java are fail-fast. This means that if the collection is modified while iterating (except through the iteratorβs own remove() method), it throws a ConcurrentModificationException.
- The remove() method can only remove elements, and it should be called only once per call to next(). Otherwise, it will throw an IllegalStateException.
Collection Interface
This is the interface through which the data structures and inner implementations become flexible. Majorly all the classes implement this interface indirectly allowing changing implementation by just changing object assigned to Collection reference of it.
//ArrayList
Collection<Integer> c = new ArrayList<>():
c.add(1);
c.add(2);
c.contains(1);
Collection<Integer> c1 = new LinkedList<>():
c1.addAll(c);//Array added to a linked list
/*What if i dont want arraylist but now i want a priority queue for applying efficient algorithms such as findmax and find min*/
//Just Change Object - SIMPLE! (This is nothing but polymorphism)
Collection<Integer> c = new **PriorityQueue**<>():
c.add(1);
c.add(2);
c.contains(1);
Methods of Collection Interface
-
int size
: Returns size of collection. -
boolean isEmpty
: Returns true if collection is empty. -
boolean contains(Object o)
: Returns true if Object o exists in collection. -
Iterator<E> iterator()
: Returns a iterator pointing to a collection. -
Object[] toArray()
: Coverts a collection to a array of Object type. -
<T> T[] toArray(T[] a)
: Returns an array containing all elements of the collection; the runtime type of the returned array is that of the specified array. -
boolean add(E e)
: Adds element e to the collection. Returns true if operation is successfull. -
boolean remove(Object o)
: Removes a object o from the collection. Returns true if operation is successfull. -
boolean containsAll(Collection<?> c)
: Returns true if all elements in both collections are same. Returns true if operation is successfull. 10.boolean addAll(Collection<? extends E> c)
: Adds all element of both the collections. Returns true if operation is successfull. -
boolean removeAll(Collection<?> c)
: Removes element of collection c from the caller collection. Returns true if operation is successfull. -
boolean retainAll(Collection<?> c)
: Retains only the elements present in collection c. -
void clear()
: Clears all the elements from the collection.
By implementing collection class we can override above methods to create a custom collection. Below is example for same.
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.NoSuchElementException;
public class CustomCollection<E> implements Collection<E> {
private final ArrayList<E> list = new ArrayList<>();
@Override
public int size() {
return list.size();
}
@Override
public boolean isEmpty() {
return list.isEmpty();
}
@Override
public boolean contains(Object o) {
return list.contains(o);
}
@Override
public Iterator<E> iterator() {
return new Iterator<E>() {
private int index = 0;
@Override
public boolean hasNext() {
return index < list.size();
}
@Override
public E next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
return list.get(index++);
}
};
}
@Override
public Object[] toArray() {
return list.toArray();
}
@Override
public <T> T[] toArray(T[] a) {
return list.toArray(a);
}
@Override
public boolean add(E e) {
return list.add(e);
}
@Override
public boolean remove(Object o) {
return list.remove(o);
}
@Override
public boolean containsAll(Collection<?> c) {
return list.containsAll(c);
}
@Override
public boolean addAll(Collection<? extends E> c) {
return list.addAll(c);
}
@Override
public boolean removeAll(Collection<?> c) {
return list.removeAll(c);
}
@Override
public boolean retainAll(Collection<?> c) {
return list.retainAll(c);
}
@Override
public void clear() {
list.clear();
}
}
List Interface
The List interface in Java is a part of the Java Collections Framework and extends the Collection interface. It represents an ordered collection (also known as a sequence) that allows for positional access, duplicate elements, and iteration over its elements. The List interface is implemented by several classes, such as ArrayList, LinkedList, Vector, and Stack.
Key Characteristics of the List Interface:
- Ordered Collection: A List preserves the insertion order of elements, meaning elements can be accessed by their index.
- Allows Duplicates: A List can contain duplicate elements, unlike sets which do not allow duplicates.
- Positional Access: Elements in a List can be accessed, added, or removed by their index.
- Iteration: The List interface allows for enhanced for-loops, as well as iteration using Iterator or ListIterator.
Commonly Used Methods of List Interface:
All collection interface methods are also implemented by List interface as List interface extends Collection interface.
- void add(int index, E element): Inserts the specified element E at the specified index in this list.
- E get(int index): Returns the element at the specified position in this list.
- E remove(int index): Removes the element at the specified position in this list.
- E set(int index, E element): Replaces the element at the specified position in this list with the specified element.
- int indexOf(Object o): Returns the index of the first occurrence of the specified element, or -1 if the list does not contain the element.
- int lastIndexOf(Object o): Returns the index of the last occurrence of the specified element, or -1 if the list does not contain the element.
- List subList(int fromIndex, int toIndex): Returns a view of the portion of this list between the specified fromIndex, inclusive, and toIndex, exclusive.
import java.util.ArrayList;
import java.util.List;
public class ListExample {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("Java");
list.add("Collections");
list.add("Framework");
// Accessing elements by index
System.out.println("First Element: " + list.get(0));
// Removing an element by index
list.remove(1);
System.out.println("After Removal: " + list);
// Updating an element
list.set(1, "Updated Element");
System.out.println("Updated List: " + list);
// Using a sublist
List<String> sublist = list.subList(0, 1);
System.out.println("Sublist: " + sublist);
}
}```
---
## **Set Interface in Java **
The Set interface in Java is part of the java.util package and extends the Collection interface. A Set does not allow duplicate elements and is primarily used to store unique items. The Set interface is implemented by various classes such as HashSet, LinkedHashSet, and TreeSet.
Common Characteristics of Set Interface:
No Duplicate Elements: The Set interface ensures that there are no duplicate elements.
Unordered Collection: Most implementations of the Set do not maintain any specific order (except LinkedHashSet which maintains insertion order and TreeSet which maintains sorted order).
Null Elements: Set can contain a single null element, but only certain implementations like HashSet allow this.
Note : There are no new methods introduced in set interface. All methods are overrided from collection interface, and the implementation is tweaked as per the core idea of set(storing unique values).
---
## **Queue & Deque Interfaces **
**Queue Interface in Java**
The Queue interface is a part of the Java Collections Framework that models a First-In-First-Out (FIFO) data structure. Elements are added to the end of the queue and are removed from the front. The Queue interface is generally used for managing a collection of elements that are processed sequentially.
**Key Characteristics of the Queue Interface:**
1. FIFO Order: Elements are processed in the order in which they are added.
2. Methods for Adding and Removing: The interface provides two sets of methods for inserting, removing, and examining elements. One set throws an exception if the operation fails, and the other returns a special value (null or false).
3. Head and Tail: The head of the queue is the element that will be removed first, and the tail is where new elements are added.
**Commonly Used Methods of Queue Interface:**
1. boolean add(E e): Inserts the specified element into the queue, throws an IllegalStateException if the queue is full.
2. boolean offer(E e): Inserts the specified element into the queue, returns false if the queue is full.
3. E remove(): Removes the head of the queue, throws a NoSuchElementException if the queue is empty.
4. E poll(): Removes the head of the queue, returns null if the queue is empty.
5. E element(): Retrieves, but does not remove, the head of the queue, throws a NoSuchElementException if the queue is empty.
6.E peek(): Retrieves, but does not remove, the head of the queue, returns null if the queue is empty.
Queue Example using Queue Interface
import java.util.LinkedList;
import java.util.Queue;
public class QueueExample {
public static void main(String[] args) {
Queue queue = new LinkedList<>();
queue.offer("Java");
queue.offer("Collection");
queue.offer("Framework");
// Peek at the head of the queue
System.out.println("Head: " + queue.peek());
// Poll and remove elements
while (!queue.isEmpty()) {
System.out.println("Removing: " + queue.poll());
}
}
}
---
**Deque Interface in Java**
The Deque (Double-Ended Queue) interface extends the Queue interface. It allows elements to be added or removed from both ends (head or tail), making it more flexible than the Queue interface, which only supports adding at the end and removing from the front.
**Key Characteristics of Deque:**
1. Double-Ended: Elements can be added or removed from both ends.
2. Efficient Operations: It provides efficient operations for both ends, making it useful for stack-like or queue-like data structures.
**Commonly Used Methods of Deque Interface:**
1. void addFirst(E e): Inserts the specified element at the front of the deque.
2. void addLast(E e): Inserts the specified element at the end of the deque.
3. boolean offerFirst(E e): Inserts the specified element at the front of the deque, returns false if the deque is full.
4. boolean offerLast(E e): Inserts the specified element at the end of the deque, returns false if the deque is full.
5. E removeFirst(): Removes and returns the first element of the deque, throws a NoSuchElementException if the deque is empty.
6. E removeLast(): Removes and returns the last element of the deque, throws a NoSuchElementException if the deque is empty.
7. E pollFirst(): Removes and returns the first element of the deque, returns null if the deque is empty.
8. E pollLast(): Removes and returns the last element of the deque, returns null if the deque is empty.
9. E getFirst(): Retrieves, but does not remove, the first element of the deque, throws a NoSuchElementException if the deque is empty.
10. E getLast(): Retrieves, but does not remove, the last element of the deque, throws a NoSuchElementException if the deque is empty.
Deque Example using Deque Interface
import java.util.Deque;
import java.util.LinkedList;
public class DequeExample {
public static void main(String[] args) {
Deque deque = new LinkedList<>();
// Add elements to both ends
deque.addFirst("Front");
deque.addLast("Back");
System.out.println("First Element: " + deque.getFirst());
System.out.println("Last Element: " + deque.getLast());
// Remove elements from both ends
System.out.println("Removed First: " + deque.removeFirst());
System.out.println("Removed Last: " + deque.removeLast());
}
}
Top comments (0)