Java Collections
Java Collections
Constructors in ArrayList
In order to create an ArrayList, we need to create an object of the ArrayList class. The ArrayList class consists of various constructors which
allow the possible creation of the array list. The following are the constructors available in this class:
1. ArrayList()
This constructor is used to build an empty array list. If we wish to create an empty ArrayList with the name arr, then, it can be created as:
ArrayList arr = new ArrayList();
2. ArrayList(Collection c)
This constructor is used to build an array list initialized with the elements from the collection c. Suppose, we wish to create an ArrayList arr
which contains the elements present in the collection c, then, it can be created as:
ArrayList arr = new ArrayList(c);
3. ArrayList(int capacity)
This constructor is used to build an array list with the initial capacity being specified. Suppose we wish to create an ArrayList with the initial
size being N, then, it can be created as:
ArrayList arr = new ArrayList(N);
ArrayList in Java methods
Method Description
clear() This method is used to remove all the elements from any list.
contains? (Object o) Returns true if this list contains the specified element.
get?(int index) Returns the element at the specified position in this list.
Returns a list iterator over the elements in this list (in proper
listIterator?()
sequence).
Returns a list iterator over the elements in this list (in proper
listIterator?(int index)
sequence), starting at the specified position in the list.
remove?(int index) Removes the element at the specified position in this list.
Removes from this list all of its elements that are contained
removeAll?(Collection c)
in the specified collection.
Retains only the elements in this list that are contained in the
retainAll?(Collection<?> c)
specified collection.
// Main class
class GFG {
2. Changing Elements
After adding the elements, if we wish to change the element, it can be done using the set() method. Since an ArrayList is indexed, the
element which we wish to change is referenced by the index of the element. Therefore, this method takes an index and the updated element
which needs to be inserted at that index.
Below is the implementation of the above approach:
3. Removing Elements
In order to remove an element from an ArrayList, we can use the remove() method. This method is overloaded to perform multiple operations
based on different parameters. They are as follows:
remove(Object): This method is used to simply remove an object from the ArrayList. If there are multiple such objects, then the
first occurrence of the object is removed.
remove(int index): Since an ArrayList is indexed, this method takes an integer value which simply removes the element present at
that specific index in the ArrayList. After removing the element, all the elements are moved to the left to fill the space and the
indices of the objects are updated.
Example:
// Main class
class GFG {
// Main class
class GFG {
System.out.println();
5. Get Elements
class GFG {
public static void main (String[] args) {
ArrayList<Integer> list = new ArrayList();
// add the number
list.add(9);
list.add(5);
list.add(6);
System.out.println(list);
// get method
Integer n= list.get(1);
System.out.println("at indext 1 number is:"+n);
}
}
7. ArrayList Sort
class GFG {
public static void main(String[] args)
{
ArrayList<Integer> list = new ArrayList();
list.add(2);
list.add(4);
list.add(3);
list.add(1);
System.out.println("Before sorting list:");
System.out.println(list);
Collections.sort(list);
System.out.println("after sorting list:");
System.out.println(list);
}
}
Output
Before sorting list:
[2, 4, 3, 1]
after sorting list:
[1, 2, 3, 4]
8. Size of Elements
Java
list.add(1);
list.add(2);
list.add(3);
list.add(4);
int b = list.size();
System.out.println("The size is :" + b);
}
}
Output
The size is :4
ArrayList in Java is a class in the Java Collection framework that implements the List interface. Here are the advantages and disadvantages
of using ArrayList in Java.
Advantages of Java ArrayList
1. Dynamic size: ArrayList can dynamically grow and shrink in size, making it easy to add or remove elements as needed.
2. Easy to use: ArrayList is simple to use, making it a popular choice for many Java developers.
3. Fast access: ArrayList provides fast access to elements, as it is implemented as an array under the hood.
4. Ordered collection: ArrayList preserves the order of elements, allowing you to access elements in the order they were added.
5. Supports null values: ArrayList can store null values, making it useful in cases where the absence of a value needs to be represented.
Disadvantages of Java ArrayList
1. Slower than arrays: ArrayList is slower than arrays for certain operations, such as inserting elements in the middle of the list.
2. Increased memory usage: ArrayList requires more memory than arrays, as it needs to maintain its dynamic size and handle resizing.
3. Not thread-safe: ArrayList is not thread-safe, meaning that multiple threads may access and modify the list concurrently, leading to
potential race conditions and data corruption.
4. Performance degradation: ArrayList’s performance may degrade as the number of elements in the list increases, especially for
operations such as searching for elements or inserting elements in the middle of the list.
Stack
Java Collection framework provides a Stack class that models and implements a Stack data structure. The class is based on the basic
principle of last-in-first-out. In addition to the basic push and pop operations, the class provides three more functions of empty, search, and
peek. The class can also be said to extend Vector and treats the class as a stack with the five mentioned functions. The class can also be
referred to as the subclass of Vector.
The below diagram shows the hierarchy of the Stack class:
The class supports one default constructor Stack() which is used to create an empty stack.
Declaration:
public class Stack<E> extends Vector<E>
All Implemented Interfaces:
Serializable: It is a marker interface that classes must implement if they are to be serialized and deserialized.
Cloneable: This is an interface in Java which needs to be implemented by a class to allow its objects to be cloned.
Iterable<E>: This interface represents a collection of objects which is iterable — meaning which can be iterated.
Collection<E>: A Collection represents a group of objects known as its elements. The Collection interface is used to pass around
collections of objects where maximum generality is desired.
List<E>: The List interface provides a way to store the ordered collection. It is a child interface of Collection.
RandomAccess: This is a marker interface used by List implementations to indicate that they support fast (generally constant time)
random access.
How to Create a Stack?
In order to create a stack, we must import java.util.stack package and use the Stack() constructor of this class. The below example creates an
empty Stack.
Stack<E> stack = new Stack<E>();
operations on Stack class
1. Adding Elements: In order to add an element to the stack, we can use the push() method. This push() operation place the element at the
top of the stack.
Java
class StackDemo {
// Main Method
public static void main(String[] args)
{
// Initialization of Stack
// using Generics
Stack<String> stack2 = new Stack<String>();
stack2.push("Geeks");
stack2.push("For");
stack2.push("Geeks");
// Printing the Stack Elements
System.out.println(stack1);
System.out.println(stack2);
}
}
2. Accessing the Element: To retrieve or fetch the first element of the Stack or the element present at the top of the Stack, we can
use peek() method. The element retrieved does not get deleted or removed from the Stack.
Java
// Main Method
public static void main(String args[])
{
// Creating an empty Stack
Stack<String> stack = new Stack<String>();
3. Removing Elements: To pop an element from the stack, we can use the pop() method. The element is popped from the top of the stack
and is removed from the same.
Java
Example
In Java, the Stack class is a subclass of the Vector class and represents a last-in-first-out (LIFO) stack of objects. It extends the Vector class to
allow for easy implementation of the stack data structure.
Here’s an example of how you can use the Stack class in Java:
Java
import java.util.Stack;
METHOD DESCRIPTION
empty() It returns true if nothing is on the top of the stack. Else, returns false.
peek() Returns the element on the top of the stack, but does not remove it.
search(Object It determines whether an object exists in the stack. If the element is found,
element) It returns the position of the element from the top of the stack. Else, it returns -1.
Queue Interface In Java
The Queue interface is present in java.util package and extends the Collection interface is used to hold the elements about to be processed in
FIFO(First In First Out) order. It is an ordered list of objects with its use limited to inserting elements at the end of the list and deleting
elements from the start of the list, (i.e.), it follows the FIFO or the First-In-First-Out principle.
Being an interface the queue needs a concrete class for the declaration and the most common classes are the PriorityQueue and LinkedList in
Java. Note that neither of these implementations is thread-safe. PriorityBlockingQueue is one alternative implementation if the thread-safe
implementation is needed.
Declaration: The Queue interface is declared as:
public interface Queue extends Collection
Creating Queue Objects: Since Queue is an interface, objects cannot be created of the type queue. We always need a class which extends
this list in order to create an object. And also, after the introduction of Generics in Java 1.5, it is possible to restrict the type of object that can
be stored in the Queue. This type-safe queue can be defined as:
// Obj is the type of the object to be stored in Queue
Queue<Obj> queue = new PriorityQueue<Obj> ();
In Java, the Queue interface is a subtype of the Collection interface and represents a collection of elements in a specific order. It follows the
first-in, first-out (FIFO) principle, which means that the elements are retrieved in the order in which they were added to the queue.
The Queue interface provides several methods for adding, removing, and inspecting elements in the queue. Here are some of the most
commonly used methods:
add(element): Adds an element to the rear of the queue. If the queue is full, it throws an exception.
offer(element): Adds an element to the rear of the queue. If the queue is full, it returns false.
remove(): Removes and returns the element at the front of the queue. If the queue is empty, it throws an exception.
poll(): Removes and returns the element at the front of the queue. If the queue is empty, it returns null.
element(): Returns the element at the front of the queue without removing it. If the queue is empty, it throws an exception.
peek(): Returns the element at the front of the queue without removing it. If the queue is empty, it returns null.
The Queue interface is implemented by several classes in Java, including LinkedList, ArrayDeque, and PriorityQueue. Each of these classes
provides different implementations of the queue interface, with different performance characteristics and features.
Overall, the Queue interface is a useful tool for managing collections of elements in a specific order, and is widely used in many different
applications and industries.
Example:
Java
import java.util.LinkedList;
import java.util.Queue;
Example: Queue
Java
import java.util.LinkedList;
import java.util.Queue;
System.out.println(q);
pq.add("Geeks");
pq.add("For");
pq.add("Geeks");
System.out.println(pq);
}
}
2. Removing Elements: In order to remove an element from a queue, we can use the remove() method. If there are multiple such objects,
then the first occurrence of the object is removed. Apart from that, poll() method is also used to remove the head and return it.
Example
Java
import java.util.*;
pq.add("Geeks");
pq.add("For");
pq.add("Geeks");
pq.remove("Geeks");
3. Iterating the Queue: There are multiple ways to iterate through the Queue. The most famous way is converting the queue to the array and
traversing using the for loop. However, the queue also has an inbuilt iterator which can be used to iterate through the queue.
Example
Java
import java.util.*;
pq.add("Geeks");
pq.add("For");
pq.add("Geeks");
while (iterator.hasNext()) {
System.out.print(iterator.next() + " ");
}
}
}
Output
For Geeks Geeks
Characteristics of a Queue: The following are the characteristics of the queue:
The Queue is used to insert elements at the end of the queue and removes from the beginning of the queue. It follows FIFO concept.
The Java Queue supports all methods of Collection interface including insertion, deletion, etc.
LinkedList, ArrayBlockingQueue and PriorityQueue are the most frequently used implementations.
If any null operation is performed on BlockingQueues, NullPointerException is thrown.
The Queues which are available in java.util package are Unbounded Queues.
The Queues which are available in java.util.concurrent package are the Bounded Queues.
All Queues except the Deques supports insertion and removal at the tail and head of the queue respectively. The Deques support
element insertion and removal at both ends.
Classes that implement the Queue Interface:
1. PriorityQueue: PriorityQueue class which is implemented in the collection framework provides us a way to process the objects based on
the priority. It is known that a queue follows the First-In-First-Out algorithm, but sometimes the elements of the queue are needed to be
processed according to the priority, that’s when the PriorityQueue comes into play. Let’s see how to create a queue object using this class.
import java.util.*;
class GfG {
2. LinkedList: LinkedList is a class which is implemented in the collection framework which inherently implements the linked list data
structure. It is a linear data structure where the elements are not stored in contiguous locations and every element is a separate object with a
data part and address part. The elements are linked using pointers and addresses. Each element is known as a node. Due to the dynamicity
and ease of insertions and deletions, they are preferred over the arrays or queues. Let’s see how to create a queue object using this class.
Example
import java.util.*;
class GfG {
3. PriorityBlockingQueue: It is to be noted that both the implementations, the PriorityQueue and LinkedList are not thread-safe.
PriorityBlockingQueue is one alternative implementation if thread-safe implementation is needed. PriorityBlockingQueue is an unbounded
blocking queue that uses the same ordering rules as class PriorityQueue and supplies blocking retrieval operations.
Since it is unbounded, adding elements may sometimes fail due to resource exhaustion resulting in OutOfMemoryError. Let’s see how to
create a queue object using this class.
Example
import java.util.concurrent.PriorityBlockingQueue;
import java.util.*;
class GfG {
public static void main(String args[])
{
// Creating empty priority
// blocking queue
Queue<Integer> pbq
= new PriorityBlockingQueue<Integer>();
// Adding items to the pbq
// using add()
pbq.add(10);
pbq.add(20);
pbq.add(15);
Method Description
This method is used to add an element at a particular index in the queue. When a single parameter is
add(int index, element)
passed, it simply adds the element at the end of the queue.
addAll(int index, Collection This method is used to add all the elements in the given collection to the queue. When a single
collection) parameter is passed, it adds all the elements of the given collection at the end of the queue.
This method is used to remove all the elements in the queue. However, the reference of the queue
clear()
created is still stored.
remove() This method is used to remove the element from the front of the queue.
This method removes an element from the specified index. It shifts subsequent elements(if any) to left
remove(int index)
and decreases their indexes by 1.
remove(element) This method is used to remove and return the first occurrence of the given element in the queue.
This method replaces elements at a given index with the new element. This function returns the
set(int index, element)
element which was just replaced by a new element.
This method returns the first occurrence of the given element or -1 if the element is not present in the
indexOf(element)
queue.
This method returns the last occurrence of the given element or -1 if the element is not present in the
lastIndexOf(element)
queue.
Method Description
equals(element) This method is used to compare the equality of the given element with the elements of the queue.
hashCode() This method is used to return the hashcode value of the given queue.
This method is used to check if the queue is empty or not. It returns true if the queue is empty, else
isEmpty()
false.
This method is used to check if the queue contains the given element or not. It returns true if the queue
contains(element)
contains the element.
containsAll(Collection
This method is used to check if the queue contains all the collection of elements.
collection)
sort(Comparator comp) This method is used to sort the elements of the queue on the basis of the given comparator.
boolean add(object) This method is used to insert the specified element into a queue and return true upon success.
boolean offer(object) This method is used to insert the specified element into the queue.
This method is used to retrieve and removes the head of the queue, or returns null if the queue is
Object poll()
empty.
Object element() This method is used to retrieves, but does not remove, the head of queue.
This method is used to retrieves, but does not remove, the head of this queue, or returns null if this
Object peek()
queue is empty.
Hashtable in Java
The Hashtable class implements a hash table, which maps keys to values. Any non-null object can be used as a key or as a value. To
successfully store and retrieve objects from a hashtable, the objects used as keys must implement the hashCode method and the equals
method.
The java.util.Hashtable class is a class in Java that provides a key-value data structure, similar to the Map interface. It was part of the original
Java Collections framework and was introduced in Java 1.0.
However, the Hashtable class has since been considered obsolete and its use is generally discouraged. This is because it was designed prior to
the introduction of the Collections framework and does not implement the Map interface, which makes it difficult to use in conjunction with
other parts of the framework. In addition, the Hashtable class is synchronized, which can result in slower performance compared to other
implementations of the Map interface.
In general, it’s recommended to use the Map interface or one of its implementations (such as HashMap or ConcurrentHashMap) instead of
the Hashtable class.
Here’s an example of how to use the Hashtable class:
Java
import java.util.Enumeration;
import java.util.Hashtable;
In conclusion, while the Hashtable class still exists in Java and can still be used, it’s generally recommended to use the Map interface or one
of its implementations instead.
Features of Hashtable
It is similar to HashMap, but is synchronized.
Hashtable stores key/value pair in hash table.
In Hashtable we specify an object that is used as a key, and the value we want to associate to that key. The key is then hashed, and
the resulting hash code is used as the index at which the value is stored within the table.
The initial default capacity of Hashtable class is 11 whereas loadFactor is 0.75.
HashMap doesn’t provide any Enumeration, while Hashtable provides not fail-fast Enumeration.
Declaration:
public class Hashtable<K,V> extends Dictionary<K,V> implements Map<K,V>, Cloneable, Serializable
Type Parameters:
K – the type of keys maintained by this map
V – the type of mapped values
The Hierarchy of Hashtable
Hashtable implements Serializable, Cloneable, Map<K,V> interfaces and extends Dictionary<K,V>. The direct subclasses
are Properties, UIDefaults.
Constructors:
In order to create a Hashtable, we need to import it from java.util.Hashtable. There are various ways in which we can create a Hashtable.
1. Hashtable(): This creates an empty hashtable with the default load factor of 0.75 and an initial capacity is 11.
Hashtable<K, V> ht = new Hashtable<K, V>();
Java
// Java program to demonstrate
// adding elements to Hashtable
import java.io.*;
import java.util.*;
class AddElementsToHashtable {
public static void main(String args[])
{
// No need to mention the
// Generic type twice
Hashtable<Integer, String> ht1 = new Hashtable<>();
// Initialization of a Hashtable
// using Generics
Hashtable<Integer, String> ht2
= new Hashtable<Integer, String>();
ht2.put(4, "four");
ht2.put(5, "five");
ht2.put(6, "six");
2. Hashtable(int initialCapacity): This creates a hash table that has an initial size specified by initialCapacity and the default load factor is
0.75.
Hashtable<K, V> ht = new Hashtable<K, V>(int initialCapacity);
Java
import java.io.*;
import java.util.*;
class AddElementsToHashtable {
public static void main(String args[])
{
// No need to mention the
// Generic type twice
Hashtable<Integer, String> ht1 = new Hashtable<>(4);
// Initialization of a Hashtable
// using Generics
Hashtable<Integer, String> ht2
= new Hashtable<Integer, String>(2);
3. Hashtable(int size, float fillRatio): This version creates a hash table that has an initial size specified by size and fill ratio specified by
fillRatio. fill ratio: Basically, it determines how full a hash table can be before it is resized upward and its Value lies between 0.0 to 1.0.
Hashtable<K, V> ht = new Hashtable<K, V>(int size, float fillRatio);
Java
import java.io.*;
import java.util.*;
class AddElementsToHashtable {
public static void main(String args[])
{
// No need to mention the
// Generic type twice
Hashtable<Integer, String> ht1
= new Hashtable<>(4, 0.75f);
// Initialization of a Hashtable
// using Generics
Hashtable<Integer, String> ht2
= new Hashtable<Integer, String>(3, 0.5f);
ht2.put(4, "four");
ht2.put(5, "five");
ht2.put(6, "six");
4. Hashtable(Map<? extends K,? extends V> m): This creates a hash table that is initialized with the elements in m.
Hashtable<K, V> ht = new Hashtable<K, V>(Map m);
Java
class AddElementsToHashtable {
public static void main(String args[])
{
// No need to mention the
// Generic type twice
Map<Integer, String> hm = new HashMap<>();
// Initialization of a Hashtable
// using Generics
Hashtable<Integer, String> ht2
= new Hashtable<Integer, String>(hm);
Example:
Java
import java.util.*;
import java.io.*;
import java.util.*;
class AddElementsToHashtable {
public static void main(String args[])
{
// No need to mention the
// Generic type twice
Hashtable<Integer, String> ht1 = new Hashtable<>();
// Initialization of a Hashtable
// using Generics
Hashtable<Integer, String> ht2
= new Hashtable<Integer, String>();
ht2.put(1, "Geeks");
ht2.put(2, "For");
ht2.put(3, "Geeks");
2. Changing Elements: After adding the elements if we wish to change the element, it can be done by again adding the element with
the put() method. Since the elements in the hashtable are indexed using the keys, the value of the key can be changed by simply inserting the
updated value for the key for which we wish to change.
Java
import java.io.*;
import java.util.*;
class UpdatesOnHashtable {
public static void main(String args[])
{
// Initialization of a Hashtable
Hashtable<Integer, String> ht
= new Hashtable<Integer, String>();
3. Removing Element: In order to remove an element from the Map, we can use the remove() method. This method takes the key value and
removes the mapping for a key from this map if it is present in the map.
Java
import java.io.*;
import java.util.*;
class RemovingMappingsFromHashtable {
// Initial HashMap
System.out.println("Initial map : " + ht);
// Final Hashtable
System.out.println("Updated map : " + ht);
}
}
4. Traversal of a Hashtable: To iterate the table, we can make use of an advanced for loop. Below is the example of iterating a hashtable.
Java
import java.util.Hashtable;
import java.util.Map;
Methods of Hashtable
K – The type of the keys in the map.
V – The type of values mapped in the map.
METHOD DESCRIPTION
compute(K key, BiFunction<? super Attempts to compute a mapping for the specified key and its current mapped value
K,? super V,? extends V> remappingFunction) (or null if there is no current mapping).
If the specified key is not already associated with a value (or is mapped to null),
computeIfAbsent(K key, Function<? super K,?
attempts to compute its value using the given mapping function and enters it into
extends V> mappingFunction)
this map unless null.
computeIfPresent(K key, BiFunction<? super K,? If the value for the specified key is present and non-null, attempts to compute a new
super V,? extends V> remappingFunction) mapping given the key and its current mapped value.
contains(Object value) Tests if some key maps into the specified value in this hashtable.
containsValue(Object value) Returns true if this hashtable maps one or more keys to this value.
Compares the specified Object with this Map for equality, as per the definition in
equals(Object o)
the Map interface.
Returns the value to which the specified key is mapped, or null if this map contains
get(Object key)
no mapping for the key.
hashCode() Returns the hash code value for this Map as per the definition in the Map interface.
merge(K key, V value, BiFunction<? super V,? If the specified key is not already associated with a value or is associated with null,
super V,? extends V> remappingFunction) associates it with the given non-null value.
put(K key, V value) Maps the specified key to the specified value in this hashtable.
putAll(Map<? extends K,? extends V> t) Copies all of the mappings from the specified map to this hashtable.
remove(Object key) Removes the key (and its corresponding value) from this hashtable.
METHOD DESCRIPTION
forEach(BiConsumer<? super K,? super V> Performs the given action for each entry in this map until all entries have been
action) processed or the action throws an exception.
Returns the value to which the specified key is mapped, or defaultValue if this map
getOrDefault(Object key, V defaultValue)
contains no mapping for the key.
If the specified key is not already associated with a value (or is mapped to null)
putIfAbsent(K key, V value)
associates it with the given value and returns null, else returns the current value.
METHOD DESCRIPTION
remove(Object key, Removes the entry for the specified key only if it is currently mapped to the specified
Object value) value.
replace(K key, V value) Replaces the entry for the specified key only if it is currently mapped to some value.
replace(K key, V oldValue, V newValue) Replaces the entry for the specified key only if currently mapped to the specified value.
replaceAll(BiFunction<? super K,? super V,? Replaces each entry’s value with the result of invoking the given function on that entry
extends V> function) until all entries have been processed or the function throws an exception.
Must Read:
Differences between HashMap and HashTable in Java
Advantages of Hashtable:
1. Thread-safe: The Hashtable class is thread-safe, meaning that multiple threads can access it simultaneously without causing data
corruption or other synchronization issues.
2. Simple to use: The Hashtable class is simple to use and provides basic key-value data structure functionality, which can be useful
for simple cases.
Disadvantages of Hashtable:
1. Obsolete: The Hashtable class is considered obsolete and its use is generally discouraged. This is because it was designed prior to
the introduction of the Collections framework and does not implement the Map interface, which makes it difficult to use in
conjunction with other parts of the framework.
2. Limited functionality: The Hashtable class provides basic key-value data structure functionality, but does not provide the full range
of functionality that is available in the Map interface and its implementations.
3. Poor performance: The Hashtable class is synchronized, which can result in slower performance compared to other implementations
of the Map interface, such as HashMap or ConcurrentHashMap.