Collection Framework
|
| Advance Java | IndianTechnoEra |
Introduction:
The Collection Framework in Java provides a set of interfaces and classes for storing and manipulating groups of data.
It provides a unified architecture for representing and manipulating collections, which makes it easier to write reusable code that can work with different types of collections.
The key features of the Collection Framework include:
1. Interfaces: The Collection Framework provides several interfaces such as `List`, `Set`, `Queue`, and `Map`, which define the behavior and functionality of different types of collections.
2. Implementations: The Collection Framework also provides various concrete implementations of these interfaces, such as `ArrayList`, `LinkedList`, `HashSet`, `HashMap`, and many others.
3. Algorithms: The Collection Framework provides a set of algorithms that can be applied to any collection, such as sorting, searching, and shuffling.
4. Iterators: The Collection Framework provides a way to iterate over the elements in a collection using iterators, which are objects that implement the `Iterator` interface.
Advantages of the Collection Framework:
1. Reusability: The Collection Framework provides a set of reusable data structures and algorithms that can be used in a wide range of applications.
2. Efficiency: The Collection Framework provides efficient implementations of data structures such as lists, sets, and maps, which can improve the performance of applications.
3. Type safety: The use of generics in the Collection Framework provides type safety, which helps to prevent type errors at compile time.
4. Interoperability: The Collection Framework is designed to work with other Java technologies, such as the Java Streams API and the Java Persistence API.
Disadvantages of the Collection Framework:
1. Complexity: The Collection Framework can be complex and difficult to understand for beginners.
2. Overhead: The use of the Collection Framework can introduce some overhead due to the additional objects and method call that are required.
3. Memory usage: The Collection Framework can consume more memory than traditional arrays, especially for small collections.
Overall, the advantages of the Collection Framework outweigh the disadvantages, and it is widely used in Java applications for its efficiency, reusability, and type safety.
Collection Framework Hierarchy:
At the top of the hierarchy is the Collection interface, which defines the basic functionality that all collections must provide. Below the Collection interface are two main subinterfaces: List and Set.
Generic Class:
Generic classes are classes that can be parameterized with one or more types. They allow you to create reusable code that can work with different types of data without having to rewrite the code for each type.
In Java, generic classes are defined using angle brackets (<>) and a type parameter that represents the type that will be used with the class.
The syntax for defining a generic class in Java is similar to that of C#. Here are some examples of generic classes in Java:
ArrayList<T>: A generic class to create a dynamic array of objects of type T.
HashMap<K, V>: A generic class to create a collection of key-value pairs, with K representing the type of the keys and V representing the type of the values.
Queue<T>: A generic class to create a queue of objects of type T.
Stack<T>: A generic class to create a stack of objects of type T.
LinkedList<T>: A generic class to create a linked list of objects of type T.
HashSet<T>: A generic class to create a set of objects of type T, with no duplicates allowed.
Optional<T>: A generic class that allows a value type to be assigned a null value.
TreeMap<K, V>: A generic class to create a sorted collection of key-value pairs, with K representing the type of the keys and V representing the type of the values.
Pair<T1, T2>: A generic class to create a pair of two objects of types T1 and T2.
ObservableList<T>: A generic class to create a collection of objects of type T that notifies listeners when items are added, removed, or updated.
List:
A List is an ordered collection of elements that allows duplicates.
It extends or inherits from the collection interface.
It contains all the existing collection methods and it has also some extra methods.
Elements can be added and removed from any position in the list.
Two commonly used classes that implement the List interface are ArrayList and LinkedList.
Example:
List<String> list = new ArrayList<>();
list.add("apple");
list.add("banana");
list.add("cherry");
System.out.println(list); // [apple, banana, cherry]
List Collection Methods:
add(E e): Adds the element 'e' at the end of the collection.
addAll(Collection<E> c): Adds all the elements of collection 'c' at the end of the current collection.
remove(Object o): Removes the first occurrence of the object 'o' from the collection.
removeAll(Collection<E> c): Removes all the elements from the collection that are present in collection 'c'.
retainAll(Collection<E> c): Removes all the elements from the collection that are not present in collection 'c'.
clear(): Removes all the elements from the collection.
isEmpty(): Returns true if the collection is empty, otherwise false.
contains(Object o): Returns true if the collection contains the object 'o', otherwise false.
containsAll(Collection<E> c): Returns true if the collection contains all the elements of collection 'c', otherwise false.
equals(Object o): Returns true if the collection is equal to the object 'o', otherwise false.
size(): Returns the number of elements in the collection.
iterator(): Returns an iterator that allows to access the elements in forward direction.
toArray(): Returns an array containing all the elements of the collection.
List Collection Extra Methods:
add(int index, E e): Adding at a given index
addAll(int index, Collection<E> e): Add collection to another collection from a particular index, and existing elements will shift ahead
remove(int index): Remove object by giving an index and shifting all elements over the free space
get(int index): Give the object
set(int index, E e): Replace the object at given index
subList(int fromIndex, int toIndex): Make a copy of a collection as a new.
indexOf(Object o): Give the index of the given object. It searches from starting
lastIndexOf(Object o): Give the index of a given object. It searches for the last one
listIterator(): It allows to access in bi-directional objects forward and backward
listIterator(int index): At the beginning of a point or from a particular point
ArrayList:
ArrayList is a resizable array implementation of the List interface.
It is backed by an array, which means that elements can be accessed using an index.
It uses the dynamic array internally to store elements.
Manipulation is slow because internally it uses an array, if one element remove then all elements shifted in memory.
It consumes less memory.
It acts as a list only because it implements a List only.
It is better for storing and accessing data.
It has constant time (O(1)) access for retrieving elements by index, but
It has linear time (O(n)) for inserting or removing elements from the middle of the list.
Example:
ArrayList Methods:
add(E e): Adds the specified element to the end of the list.
add(int index, E element): Inserts the specified element at the specified position in the list.
get(int index): Returns the element at the specified position in the list.
set(int index, E element): Replaces the element at the specified position in the list with the specified element.
remove(Object o): Removes the first occurrence of the specified element from
the list, if it is present.
size(): Returns the number of elements in the list.
isEmpty(): Returns true if the list contains no elements.
indexOf(Object o): Returns the index of the first occurrence of the specified element in the list, or -1 if the list does not contain the element.
contains(Object o): Returns true if the list contains the specified element.
toArray(): Returns an array containing all of the elements in the list in proper sequence.
clear(): Removes all of the elements from the list.
addAll(Collection<? extends E> c): Appends all of the elements in the specified collection to the end of the list, in the order that they are returned by the collection's iterator.
Example:
1. add(int index, E element):
Inserts the specified element at the specified position in this list. Shifts the element currently at that position (if any) and any subsequent elements to the right (adds one to their indices).
Example:
2. addAll(Collection<? extends E> c): Appends all of the elements in the specified collection to the end of this list, in the order that they are returned by the specified collection's iterator.
Example:
3. clear(): Removes all of the elements from this list. The list will be empty after this call returns.
Example:
4. contains(Object o): Returns true if this list contains the specified element.
Example:
5. get(int index): Returns the element at the specified position in this list.
Example:
6. indexOf(Object o): Returns the index of the first occurrence of the specified element in this list, or -1 if this list does not contain the element.
Example:
7. isEmpty(): Returns true if this list contains no elements.
Example:
8. remove(int index): Removes the element at the specified position in this list. Shifts any subsequent elements to the left (subtracts one from their indices).
Example:
9. set(int index, E element): Replaces the element at the specified position in this list with the specified element.
Example:
10. size(): Returns the number of elements in this list.
Example:
These are just a few examples of the many methods that are available in the ArrayList implementation of the List interface. By using the appropriate methods, you can manipulate the list to suit your needs.
LinkedList:
LinkedList is a doubly linked list implementation of the List interface.
It is backed by nodes that contain references to the previous and next elements in the list.
It uses a doubly linked list to store the element internally.
Manipulation is faster than ArrayList because it uses a doubly linked list, so no shifting is required in memory.
It consumes more memory because it also stores previous and next reference with data.
It acts as a list and Deque
It is better for manipulating data (like add remove).
It has constant time (O(1)) access for inserting or removing elements from the middle of the list, but
It has linear time (O(n)) for accessing elements by index.
Example:
List<String> list = new LinkedList<>();
list.add("apple");
list.add("banana");
list.add("cherry");
System.out.println(list); // [apple, banana, cherry]
LinkedList Methods:
Here are some additional methods that are specific to the LinkedList implementation of the List interface:
addFirst(E e): Adds the specified element to the beginning of the linked list.
addLast(E e): Adds the specified element to the end of the linked list.
getFirst(): Returns the first element in the linked list.
getLast(): Returns the last element in the linked list.
removeFirst(): Removes and returns the first element in the linked list.
removeLast(): Removes and returns the last element in the linked list.
offer(E e): Adds the specified element to the end of the linked list and returns true if the operation was successful.
offerFirst(E e): Adds the specified element to the beginning of the linked list and returns true if the operation was successful.
offerLast(E e): Adds the specified element to the end of the linked list and returns true if the operation was successful.
peek(): Returns the first element in the linked list without removing it.
peekFirst(): Returns the first element in the linked list without removing it.
peekLast(): Returns the last element in the linked list without removing it.
poll(): Removes and returns the first element in the linked list, or returns null if the linked list is empty.
pollFirst(): Removes and returns the first element in the linked list, or returns null if the linked list is empty.
pollLast(): Removes and returns the last element in the linked list, or returns null if the linked list is empty.
push(E e): Adds the specified element to the beginning of the linked list, equivalent to addFirst(E e).
pop(): Removes and returns the first element in the linked list, equivalent to removeFirst().
Example:
LinkedList and ArrayList:
LinkedList and ArrayList are the two most commonly used implementations of the List interface. ArrayList is faster for accessing elements by index, while LinkedList is faster for adding or removing elements from the middle of the list. It's important to choose the right implementation based on the specific use case.
Set:
A Set is an unordered collection of elements that does not allow duplicates but unique.
Elements can be added and removed from the set, but there is no way to access elements by index.
interface set extends collection
It does not have any extra methods
Set Collection Methods:
add(E e): Add element at the end of the collection mostly
addAll(Collection<E> c): Add a collection to another collection
remove(Object o);
removeAll(Collection<E> c):
retainAll(Collection<E> c):
clear():
isEmpty():
contains(Object o): Search for an object and return true and false
containsAll(Collection<E> c):
equals(Object o):
Size(): Give the size of object
iterator(): Allow to access the element in the forward direction
toArray(): Show in an ordered form
Two commonly used classes that implement the Set interface are
- HashSet and
- TreeSet.
HashSet:
HashSet is a hash table implementation of the Set interface.
It uses the hashCode() and equals() methods of the elements to determine uniqueness and to store and retrieve the elements.
It has constant time (O(1)) for adding and removing elements, but the order of the elements is not guaranteed.
Example:
TreeSet:
TreeSet is a red-black tree implementation of the Set interface. It keeps the elements in sorted order according to their natural ordering or a specified Comparator. It has logarithmic time (O(log n)) for adding and removing elements, but accessing elements by index is not supported.
In addition to List and Set, there are also other interfaces in the Collection Framework, such as Queue and Map.
HashSet and TreeSet:
HashSet and TreeSet are the two most commonly used implementations of the Set interface. HashSet is faster for adding or removing elements, while TreeSet is faster for checking if an element is present or iterating over the elements in sorted order. It's important to choose the right implementation based on the specific use case.
Queue:
A Queue is a collection that orders its elements in a specific way for processing.
It is useful for supporting the FIFO mechanism.
Elements can be added to the end of the queue and removed from the beginning of the queue.
One commonly used class that implements the Queue interface is PriorityQueue, which is a priority queue based on a binary heap data structure.
Some methods:
.add(E e): Add an element at the end
.poll(): Remove the first object, it returns null if gets empty [ aware to check null]
.remove(): Remove the first object, but if get empty and throws an exception throws NoSuchElementException [aware to handle exception]
.peek(): Give the first object of ques, and it returns null if not get elements
.element(): Give the first object of ques, and it returns an exception if not get elements
Example:
Map:
A Map is a collection that maps keys to values.
Each key can only be associated with one value.
Two commonly used classes that implement the Map interface are
- HashMap and
- TreeMap.
HashMap:
HashMap is a hash table implementation of the Map interface.
It uses the hashCode() and equals() methods of the keys to determine uniqueness and to store and retrieve the values.
It has constant time (O(1)) for adding and retrieving elements, but the order of the elements is not guaranteed.
Example:
TreeMap:
TreeMap is a red-black tree implementation of the Map interface. It keeps the keys in sorted order according to their natural ordering or a specified Comparator. It has logarithmic time (O(log n)) for adding and retrieving elements.
Example:
HashMap and TreeMap:
HashMap and TreeMap are the two most commonly used implementations of the Map interface. HashMap is faster for adding or retrieving elements, while TreeMap is faster for iterating over the keys in sorted order or checking if a key is present. It's important to choose the right implementation based on the specific use case.
Finally, there are also other classes in the Collection Framework, such as Stack and Vector, which are subclasses of List, and HashSet and LinkedHashSet, which are subclasses of Set. These classes provide additional functionality or guarantee a specific ordering of elements.
Here's some more information about the Collection Framework and some additional classes that are commonly used:
Stack:
Stack is a subclass of Vector that implements a last-in-first-out (LIFO) stack of objects.
It provides the usual push and pop operations, as well as methods for peeking at the top item and searching the stack.
Example:
Vector:
Vector is a synchronized implementation of the List interface that is similar to ArrayList.
The main difference is that Vector is thread-safe, which means that multiple threads can access and modify the vector at the same time without causing race conditions.
However, this can come at the cost of performance, since the synchronization overhead can slow down the operations.
Example:

