Collections Java
Collections Java
The implementation classes of the List interface are ArrayList, LinkedList, Stack, and Vector. The
Vector class is deprecated since Java 5.
The AbstractList class in Java is a part of the Java Collection Framework and implements the
Collection interface and the AbstractCollection class. This class provides a skeletal implementation of
the List interface to minimize the effort required to implement this interface backed by a Random
Access data store (such as an array).
To implement an unmodifiable list, for which one needs to only extend this AbstractList Class and
implement the get(int) and the size() methods.
To implement a modifiable list, for which one additionally override the set(int index, E element)
method (which otherwise throws an UnsupportedOperationException). If the list is variable-size, for
which one should override the add(int, E) and remove(int) methods.
The AbstractSequentialList class in Java is a part of the Java Collection Framework and implements
the Collection interface and the AbstractCollection class. It is used to implement an unmodifiable list,
for which one needs to only extend this AbstractList Class and implement only the get() and the size()
methods.
This class provides a skeletal implementation of the List interface to minimize the effort required to
implement this interface backed by a “sequential access” data store (such as a linked list).
Threshold
Performance of ArrayList
The time complexity of the common operations in ArrayList java.
add(): For adding a single element O(1) . Adding n element in the array list takes O(n).
add(index, element): adding element in particular index in average runs in O(n) time.
get(): is always a constant time O(1) operation.
remove(): runs in linear O(n) time. We have to iterate the entire array to find the element fit for
removal.
indexOf(): It runs over the whole array and iterates through each and every element worst case will
be the size of the array n .so, it requires O(n) time.
contains(): implementation is based on indexOf(). So it will also run in O(n) time.
The size, isEmpty, set, iterator, and listIterator operations run in constant time O(1)
When an element is added to an ArrayList it first checks whether the new element has room to fill or
it needs to grow the size of the internal array, If capacity has to be increased then the new capacity is
calculated which is 50% more than the old capacity and the array is increased by that capacity.
While adding first check method ensureCapacityInternal(size + 1); then if need to increase size then
increase…by 50% with Arrays.copyOf(arr,newsize) method.
LinkedList in Java
• which 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. It also
has a few disadvantages like the nodes cannot be accessed directly instead we need to start from the
head and follow through the link to reach a node we wish to access.
How Does LinkedList work Internally?
Since a LinkedList acts as a dynamic array and we do not have to specify the size while creating it, the
size of the list automatically increases when we dynamically add and remove items. And also, the
elements are not stored in a continuous fashion. Therefore, there is no need to increase the size.
Internally, the LinkedList is implemented using the doubly linked list data structure.
The main difference between a normal linked list and a doubly LinkedList is that a doubly linked list
contains an extra pointer, typically called the previous pointer, together with the next pointer and
data which are there in the singly linked list.
Intenrally it has Node class with three attributes
It has modCount and expectedModCount for vairable for Concurrent modification exception.
HashMap contains an array of Node and Node can represent a class having the following objects :
int hash
K key
V value
Node next
Hashing
Hashing is a process of converting an object into integer form by using the method hashCode(). It’s
necessary to write the hashCode() method properly for better performance of HashMap.
hashCode() method: hashCode() method is used to get the hash code of an object. hashCode()
method of the object class returns the memory reference of an object in integer form.
In HashMap, hashCode() is used to calculate the bucket and therefore calculate the index.
equals() method: This method is used to check whether 2 objects are equal or not. This method is
provided by the Object class. You can override this in your class to provide your implementation.
HashMap uses equals() to compare the key to whether they are equal or not. If the equals() method
return true, they are equal otherwise not equal.
Buckets: A bucket is an element of the HashMap array. It is used to store nodes. Two or more nodes
can have the same bucket. In that case, a link list structure is used to connect the nodes. Buckets are
different in capacity. A relation between bucket and capacity is as follows:
Inserting Key-Value Pair: Putting one key-value pair in the above HashMap
Integer value = 20
Node next = null
}
Inserting another Key-Value Pair: Now, putting the other pair that is,
map.put(new Key("sachin"), 30);
Steps:
Calculate hashCode of Key {“sachin”}. It will be generated as 115.
Calculate index by using index method it will be 3.
Create a node object as :
{
int hash = 115
Key key = {"sachin"}
Integer value = 30
Node next = null
}
In Case of collision: Now, putting another pair that is,
ConcurrentHashMap
ConcurrentHashMap is a thread-safe implementation of the Map interface in Java, which means
multiple threads can access it simultaneously without any synchronization issues.
One of the key features of the ConcurrentHashMap is that it provides fine-grained locking,
meaning that it locks only the portion of the map being modified, rather than the entire map.
The underlined data structure for ConcurrentHashMap is Hashtable.
At a time any number of threads are applicable for a read operation without locking the
ConcurrentHashMap object which is not there in HashMap.
In ConcurrentHashMap, the Object is divided into a number of segments according to the
concurrency level.
The default concurrency-level of ConcurrentHashMap is 16.
In ConcurrentHashMap, at a time any number of threads can perform retrieval operation but for
updated in the object, the thread must lock the particular segment in which the thread wants to
operate. This type of locking mechanism is known as Segment locking or bucket locking. Hence at a
time, 16 update operations can be performed by threads.
Inserting null objects is not possible in ConcurrentHashMap as a key or value.
default initial capacity (16), load factor (0.75) and concurrencyLevel (16).
ConcurrentHashMap vs Hashtable
Hashtable is an implementation of Map data structure
This is a legacy class in which all methods are synchronized on Hashtable instances using the
synchronized keyword.
oncurrentHashMap
ConcurrentHashMap implements Map data structure and also provide thread safety like
Hashtable.
It works by dividing complete hashtable array into segments or portions and allowing parallel
access to those segments.
The locking is at a much finer granularity at a hashmap bucket level.
Use ConcurrentHashMap when you need very high concurrency in your application.
It is a thread-safe without synchronizing the whole map.
Reads can happen very fast while the write is done with a lock on segment level or bucket level.
ConcurrentHashMap doesn’t throw a ConcurrentModificationException if one thread tries to
modify it while another is iterating over it.
ConcurrentHashMap does not allow NULL values, so the key can not be null in
ConcurrentHashMap
ConcurrentHashMap doesn’t throw a ConcurrentModificationException if one thread tries to
modify it, while another is iterating over it.
EnumMap class in Java
EnumMap class is a member of the Java Collections Framework & is not synchronized.
EnumMap is an ordered collection and they are maintained in the natural order of their keys(the
natural order of keys means the order on which enum constants are declared inside enum type )
It’s a high-performance map implementation, much faster than HashMap.
All keys of each EnumMap instance must be keys of a single enum type.
EnumMap doesn’t allow null key and throws NullPointerException when we attempt to insert the
null key.
Iterators returned by the collection views are weakly consistent: they will never throw
ConcurrentModificationException and they may or may not show the effects of any modifications
to the map that occur while the iteration is in progress.
EnumMap is internally represented as arrays. This representation is extremely compact and
efficient.
The EnumMap class in Java is a specialized map implementation that is designed
specifically for use with enum keys. An EnumMap is a compact, efficient, and fast
alternative to using a HashMap with enum keys.
The EnumMap class can only be used with keys of an enum type, which means that
it’s not suitable for use with other types of keys.
HashMap in Java
• Java HashMap is similar to HashTable, but it is unsynchronized. It allows to store the null keys as well, but there should be
only one null key object and there can be any number of null values. This class makes no guarantees as to the order of the
map.
It is the default constructor which creates an instance of HashMap with an initial
capacity of 16 and a load factor of 0.75.
Characteristics of HashMap:
A HashMap is a data structure that is used to store and retrieve values based on
keys. Some of the key characteristics of a hashmap include:
• Fast access time: HashMaps provide constant time access to elements,
which means that retrieval and insertion of elements are very fast,
usually O(1) time complexity.
• Uses hashing function: HashMaps uses a hash function to map keys to
indices in an array. This allows for a quick lookup of values based on keys.
• Stores key-value pairs: Each element in a HashMap consists of a key-
value pair. The key is used to look up the associated value.
• Supports null keys and values: HashMaps allow for null values and keys.
This means that a null key can be used to store a value, and a null value
can be associated with a key.
• Not ordered: HashMaps are not ordered, which means that the order in
which elements are added to the map is not preserved. However,
LinkedHashMap is a variation of HashMap that preserves the insertion
order.
• Allows duplicates: HashMaps allow for duplicate values, but not duplicate
keys. If a duplicate key is added, the previous value associated with the
key is overwritten.
• Thread-unsafe: HashMaps are not thread-safe, which means that if
multiple threads access the same hashmap simultaneously, it can lead to
data inconsistencies. If thread safety is required, ConcurrentHashMap can
be used.
• Capacity and load factor: HashMaps have a capacity, which is the number
of elements that it can hold, and a load factor, which is the measure of
how full the hashmap can be before it is resized.
Internal Structure of HashMap
Internally HashMap contains an array of Node and a node is represented as a class
that contains 4 fields:
1. int hash
2. K key
3. V value
4. Node next
It can be seen that the node is containing a reference to its own object. So it’s a linked
list.
IdentityHashMap class in Java
• The IdentityHashMap implements Map interface using Hashtable, using
reference-equality in place of object-equality when comparing keys (and values).
Features of IdentityHashMap
• It follows reference equality, instead of using the equals() method it uses
the == operator.
• It is not synchronized and must be synchronized externally.
• Iterators are fail-fast, throw ConcurrentModificationException in an
attempt to modify while iterating.
• This class provides constant-time performance for the basic operations
(get and put), assuming the system identity hash function
(System.identityHashCode(Object)) disperses elements properly among
the buckets. IdentityHashMap doesn’t use hashCode() method instead it
uses System.identityHashCode() method. This is a significant difference
because now you can use mutable objects as key in Map whose hash code
is likely to change when the mapping is stored inside IdentityHashMap.
HashSet in Java
•Java HashSet Features
A few important features of HashSet are mentioned below:
• Implements Set Interface.
• The underlying data structure for HashSet is HashMAp
• NULL elements are allowed in HashSet.
The LinkedHashSet is an ordered version of HashSet that maintains a doubly-linked
List across all elements.
2.
3. 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.
4. 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.
5. BlockingQueue interface supports flow control (in addition to queue) by
introducing blocking if either BlockingQueue is full or empty. A thread trying
to enqueue an element in a full queue is blocked until some other thread
makes space in the queue, either by dequeuing one or more elements or
clearing the queue completely. Similarly, it blocks a thread trying to delete
from an empty queue until some other threads insert an item.
BlockingQueue does not accept a null value. If we try to enqueue the null
item, then it throws NullPointerException.
6. Java provides several BlockingQueue implementations such
as LinkedBlockingQueue, ArrayBlockingQueue, PriorityBlockingQueue, Synch
ronousQueue, etc. Java BlockingQueue interface implementations are
thread-safe. All methods of BlockingQueue are atomic in nature and use
internal locks or other forms of concurrency control.
7. The BlockingQueue are two types:
8. 1. Unbounded Queue: The Capacity of the blocking queue will be set to
Integer.MAX_VALUE. In the case of an unbounded blocking queue, the queue
will never block because it could grow to a very large size. when you add
elements its size grows.
9. BlockingQueue blockingQueue = new LinkedBlockingDeque();
10. 2. Bounded Queue: The second type of queue is the bounded queue. In the
case of a bounded queue you can create a queue passing the capacity of the
queue in queues constructor:
11. Syntax:
12. // Creates a Blocking Queue with capacity 5
13. BlockingQueue blockingQueue = new LinkedBlockingDeque(5);
PriorityQueue in Java
•The PriorityQueue is based on the priority heap. The elements of the priority
queue are ordered according to the natural ordering, or by a Comparator provided
at queue construction time, depending on which constructor is used.
ConcurrentLinkedQueue
It is used to implement Queue with the help of LinkedList concurrently. It is
an unbounded thread-safe implementation of Queue which inserts elements at the
tail of the Queue in a FIFO(first-in-first-out) fashion. It can be used when an
unbounded Queue is shared among many threads. This class does not permit null
elements.
ArrayBlockingQueue
ArrayBlockingQueue class is a bounded blocking queue backed by an array. By
bounded, it means that the size of the Queue is fixed. Once created, the capacity
cannot be changed. Attempts to put an element into a full queue will result in the
operation blocking. Similarly attempts to take an element from an empty queue will
also be blocked. Boundness of the ArrayBlockingQueue can be achieved initially
bypassing capacity as the parameter in the constructor of ArrayBlockingQueue. s