Java Collections Framework
When working with java, you need to have a better understanding of the java collections framework. This is used to store and manipulate the group of objects. Java Collection framework on data such as searching, insertion, manipulation, and deletion.
Java Collection framework produces many interfaces(List, Set, Queue, and Deque) which we can use in different aspects of programming. So let’s have look at the key collection classes below.
TreeSet — Keeps the elements sorted and prevents duplicates.
HashMap — Store and access elements as name/value pair.
LinkedList — This gives you a better performance when you insert or delete elements from the middle of the collection.
HashSet — Prevent duplicates in the collection, and give an element, can find that elements in the collection quickly.
LinkedHashMap — Like a regular HashMap, except it can remember the order in which elements(name, value pairs) were inserted, or it can be configured to remember the order in which elements were last accessed.
Hierarchy of Collection Framework
Map interface doesn’t inherit from the Java collection framework and it has its hierarchy which maintains the key-value pair.
Why we need the Java collection framework and its advantages.
A collection — sometimes called a container — is simply an object that groups multiple elements into a single unit. Below are some of the advantages of using the Java collection framework.
This is used to increase the program quality and helps increase the speed by giving the best valuable information structure and calculations.
Helps to focus on the program’s best use rather than focusing on an outline of the collection.
Provides a consistent API, with an essential arrangement of interfaces like Collection, List, Set, List, Queue, or Map.’
New data structures that conform to the standard collection interfaces are by nature reusable. The same goes for new algorithms that operate on objects that implement these interfaces
Why do we use ArrayLists (Collections Framework) instead of Arrays?
This is a common question, which might be asked in an interview. Arrays are a simple way of constructs with linear storage of fixed size. After we initialized the array, we can not change the size of the array and this only holds the same type of data(homogeneous).
But when comes to ArrayLists, they are more sophisticated and also more flexible. We can resize the array and also can hold different types of data types in the same array. (Heterogeneous).
Let’s have a look at Java Collections Framework integrity.
The first interface within the collection framework is the iterator interface. This is used to iterate through elements of a collection class. Using iterator, we can traverse in one direction. Many classes are inherited from the iterator interface as shown in the above interface. They are,
1. List
2. Queue
3. Set
First, let’s have a look at the List interface.
- List
The List interface provides a way to store the ordered collection and this is a child interface of the collection. This allows to have duplicates value and this is storing elements in an ordered collection. Elements are stored in the ArrayList on the zero-based index.
List <dataType> arrayList= new ArrayList();
List <dataType> linkedList = new LinkedList();
List <dataType> vector= new Vector();
List <dataType> stack= new Stack();
As you can see the ArrayList, LinkedList, Vector, and Stack interfaces are built using the List interface.
1.1 ArrayList
This is using a dynamic array which we can expand the size of the array according to the need. The ArrayList maintains the insertion order and is non-synchronized. Elements in the ArrayList can be added and removed whenever you want.
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
ArrayList<String> students = new ArrayList<String>();
students.add("Student1");
students.add("Student2");
students.add("Student3");
students.add("Student4");
System.out.println(students);
}
}
//output
[Student1, Student2, Student3, Student4]
1.2 LinkedList
Uses a doubly linked list internally to store the elements. Can also have duplicate values and the LinkedList maintain an insertion order and is not synchronized. The main advantage here is, the manipulation speed of LinkedList is higher as there is no need to have shifting elements in the array.
// Import the LinkedList class
import java.util.LinkedList;
public class Main {
public static void main(String[] args) {
LinkedList<String> students = new LinkedList<String>();
students.add("Student1");
students.add("Student2");
students.add("Student3");
students.add("Student4");
System.out.println(students);
}
}//output
[Student1, Student2, Student3, Student4]
1.3 Vector
Like ArrayList
it also maintains insertion order but it is rarely used in the non-thread environment as it is synchronized and due to which it gives a poor performance in searching, adding, delete and update of its elements.
// Import the class
import java.util.*;
public class Main{
public static void main(String args[]) {
//vector of initial capacity(size) of 2
Vector<String> vec = new Vector<String>(2);
//adding the elements to vector
vec.addElement("Student1");
vec.addElement("Student2");
vec.addElement("Student3");
vec.addElement("Student4");
//display all the students in Vector
Enumeration en = vec.elements();
while(en.hasMoreElements())
System.out.print(en.nextElement() + " ");
}
}
1.4 Stack
Stack is a subclass of vectors. This is implemented according to the Last-In-First-Out (LIFO) structure as only the last inserted element can get as the first element. This provides boolean push(), boolean peek() and boolean push(Object o) methods.
import java.util.Stack;
public class StackEmptyMethodExample
{
public static void main(String[] args)
{
//creating an instance of Stack class
Stack<Integer> stk= new Stack<>();
// pushing elements into stack
stk.push(10);
stk.push(20);
stk.push(30);
stk.push(40);
//prints elements of the stack
System.out.println("Elements in Stack: " + stk);
}
}//output
Elements in Stack:[10,20,30,40]
2. Queue
This maintains the first-in-first-out order and this can also be defined as an ordered list that is used to hold the elements which are about to be processed. There are various classes like PriorityQueue, Deque, and ArrayDeque which implemented the queue interface.
2.1 Priority Queue
The PriorityQueue class provides the facility of using queues. But it does not order the elements in First-In-First-Out (FIFO) manner. It inherits AbstractQueue class.
import java.util.*;class Example{
public static void main(String args[]){
PriorityQueue<String> queue=new PriorityQueue<String>();
queue.add("Student1");
queue.add("Studnet2");
queue.add("Student3");
queue.add("Student4");
System.out.println("head:"+queue.element());
System.out.println("head:"+queue.peek());
System.out.println("Itererating through queue elements:");
Iterator itr=queue.iterator();
while(itr.hasNext()){
System.out.println(itr.next());
}
queue.remove();
queue.poll();
System.out.println("After removing two elements:");
Iterator<String> itr2=queue.iterator();
while(itr2.hasNext()){
System.out.println(itr2.next());
}
}
}Output:head:Student1
head:Student1
Iterating through queue elements:
Student1
Student2
Student3
Student4
After removing two elements:
Student1
Student2
Student3
Student4
2.2 Deque Interface
Deque stands for the double-ended queue which enables to perform the operations at both ends. The Deque interface extends the queue interface. In dequeue, we can remove and add the elements from both sides. (This example taken from https://www.geeksforgeeks.org/)
import java.util.*;
public class DequeExample {
public static void main(String[] args)
{
Deque<String> deque
= new LinkedList<String>();
// Add at last
deque.add("Element 1 (Tail)");
// Add at the first
deque.addFirst("Element 2 (Head)");
// Add at the last
deque.addLast("Element 3 (Tail)");
// Add at the first
deque.push("Element 4 (Head)");
// Add at the last
deque.offer("Element 5 (Tail)");
// Add at the first
deque.offerFirst("Element 6 (Head)");
System.out.println(deque + "\n");
// We can remove the first element
// or the last element.
deque.removeFirst();
deque.removeLast();
System.out.println("Deque after removing "
+ "first and last: "
+ deque);
}
}//output[Element 6 (Head), Element 4 (Head), Element 2 (Head), Element 1 (Tail), Element 3 (Tail), Element 5 (Tail)]Deque after removing first and last: [Element 4 (Head), Element 2 (Head), Element 1 (Tail), Element 3 (Tail)]
2.3 ArrayDeque
This ArrayDeque is implemented using the deque interface. This allows to have a deque interface and can add or delete the elements from both ends which is also resizable.
Important: ArrayDeque is faster than the ArrayList and the stack has no capacity restrictions.
import java.util.*;
public class Main {
public static void main(String[] args) {
//Creating Deque and adding elements
Deque<String> deque = new ArrayDeque<String>();
deque.add("Student1");
deque.add("Student2");
deque.add("Studnet3");
//Traversing elements
for (String str : deque) {
System.out.println(str);
}
}
}//output
Student1
Student2
Student3
3. Set Interface
This is a collection that can not contain duplicate elements. There are three main implementations of the set interfaces as shown in the above picture. We will have a quick review of all three interfaces in this section.
1. HashSet
2. SortedSet
3. LinkedHashSet
HashSet, which stores its elements in a hash table, is the best-performing implementation.
Set<data-type> s1 = new HashSet<data-type>();
Set<data-type> s2 = new LinkedHashSet<data-type>();
Set<data-type> s3 = new TreeSet<data-type>();
So let’s have look at these interfaces.
3.1 HashSet
Java HashSet class is used to create a collection that uses a hash table for storage. This inherits the AbstractSet class and implements the Set interface.
Importance of HashSet,
1. HashSet allows null values
2. HashSet stores the elements by using a mechanism called hashing.
3. HashSet class is non-synchronized.
4. HashSet is the best approach for search operations.
What is the difference between List and Set?
A list can contain duplicate elements whereas Set contains unique elements only. (note: the order may differ from the actual as this one has an unordered list)
import java.util.*;
class HashSetExample {
public static void main(String args[]){
//Creating HashSet
HashSet<String> set=new HashSet();
//Add elements to HashSet
set.add("Student1");
set.add("Student2");
set.add("Student3");
set.add("Student4");
set.add("Student5");
Iterator<String> i=set.iterator();
while(i.hasNext())
{
System.out.println(i.next());
}
}
}//output
Student4
Student5
Student3
Student2
Student1
3.2 LinkedHashSet
LinkedHashSet extends the HashSet class and implements the Set interface. This also contains the unique values as elements and maintains the insertion order while permitting null elements. (note: the order may differ from actual as this one has an unordered list)
import java.util.*;
class LinkedHashSetExample {
public static void main(String args[]){
//Creating LinkedHashSet
LinkedHashSet<String> set=new LinkedHashSet();
//adding elements to linkedhashset
set.add("Student1");
set.add("Student2");
set.add("Student3");
set.add("Student4");
set.add("Student5");
Iterator<String> i=set.iterator();
while(i.hasNext())
{
System.out.println(i.next());
}
}
}//output
Student4
Student5
Student3
Student2
Student1
3.3 SortedSet Interface
SortedSet interface is the alternate of the Set interface that provides a total ordering on its elements. The elements of the SortedSet are arranged in ascending order. The SortedSet provides additional methods that inhibit the natural ordering of the elements.
SortedSet<data-type> set = new TreeSet();
3.3.1 TreeSet
This TreeSet class implements the Set interface that uses a tree for storage. This TreeSet is also contained unique elements and the access and retrieval time of TreeSet is quite fast. The elements in the TreeSet are stored in ascending order.
Some of the unique features of TreeSet are given below.
Like HashSet, this also has unique elements.
Access time and retrieval time are quite fast.
Doesn’t allow null values.
Always maintain ascending order.
import java.util.*;
class TreeSetExample{
public static void main(String args[]){
//Creating the treeSet
TreeSet<String> al=new TreeSet<String>();
al.add("Student1");
al.add("Student2");
al.add("Student3");
al.add("Student4");
//Traversing elements
Iterator<String> itr=al.iterator();
while(itr.hasNext()){
System.out.println(itr.next());
}
}
}//output
Student1
Student2
Student3
Student4
So in this tutorial, we have discussed the Java Collection Framework and its components. This is useful when you developing a basic application also. You need to have a proper idea of how things going with the Java Collection framework before going into development. So I hope, this tutorial will help you to achieve the best practices of Java development using Collections. See you in the next tutorial. Until then bye.