ArrayList, LinkedList, Vector, Stack, HashSet, HashMap, and Hashtable are just a few examples of the dynamically allocated data structures that are supported in Java Programming. The Collection Framework is a uniform design that requires all classes to have common characteristics. In this article, we are going to explain the complete Java Collection Framework along with data structures in Java and working with collections in Java. Join SLA Institute for the best practices of collection framework through our Java Training in Chennai.
Java Collection Framework: A Brief Overview
A variety of interfaces and classes are available in the Java collections framework to construct different data structures and algorithms. For example, the doubly-linked list data structure is implemented by the collections framework’s LinkedList class.
Interfaces of Collection Framework
There are several interfaces offered by the Java collections framework. These APIs offer a variety of ways to handle various operations on collections.
Java Collection Interface
The Collection interface is the primary interface in the hierarchy of the collections framework. Java offers implementations of the Collection interface’s subinterfaces, such as List, Set, and Queue, but not the Collection interface itself. Visit Java Collection Interface for further information.
There are two groups of collection interfaces. The descendants of the most fundamental interface, java.util.Collection, are as follows:
java.util.Set
java.util.SortedSet
java.util.NavigableSet
java.util.Queue
java.util.concurrent.BlockingQueue
java.util.concurrent.TransferQueue
java.util.Deque
java.util.concurrent.BlockingDeque
The other collection interfaces are not actual collections; rather, they are based on java.util.Map. These interfaces do, however, have collection-view methods that let you manage them as collections. The following descendants of Map exist:
java.util.SortedMap
java.util.NavigableMap
java.util.concurrent.ConcurrentMap
java.util.concurrent.ConcurrentNavigableMap
The collection interfaces have a lot of modification methods that are marked as optional. Implementations are free to forgo performing one or more of these actions, tossing an UnsupportedOperationException runtime exception in the process. Whatever optional operations are supported for each implementation must be specified in the documentation. To help with this specification, the following terms are introduced:
- Collections that do not support modification operations like add, remove, and clear are known as unmodifiable collections. Changeable collections are those that can be modified.
- Collections are regarded as immutable if they also promise that changes to the Collection object won’t be seen. Mutable collections are those that are not immutable.
- Fixed-size lists are those that promise that their size will not change even if the elements do. Variable-size lists are those that are not fixed-size.
- Random access lists are lists that enable quick (often constant time) index element access. Sequential access lists are lists that do not offer quick indexed element access. Using the RandomAccess marker interface, lists can promote their support for random access. Because of this, generic algorithms can adapt their behavior to perform well when used with random or sequential access lists.
Some implementations limit the types of components (or keys and values in the case of Maps) that can be stored. Potential limitations include mandating that components:
- Be a specific type
- Be not null
- Follow some arbitrary rules.
Collection Implementations
Classes with names in the manner generally implement collection interfaces. The following table lists the general-purpose implementations:
Interface | Hash Table | Resizable Array | Balanced Tree | Linked List | Hash Table + Linked List |
Set | HashSet | TreeSet | LinkedHashSet | ||
List | ArrayList | LinkedList | |||
Deque | ArrayQueue | LinkedList | |||
Map | HashMap | TreeMap | LinkedHashMap |
The items that can be included in the general-purpose implementations are not constrained and they support all of the optional operations in the collection interfaces. Although they lack synchronization, the Collections class has static factories known as “synchronization wrappers” that can be used to give many unsynchronized collections synchronization. All of the new implementations have fast iterators that fail cleanly and promptly when they detect an invalid concurrent update (rather than behaving erratically).
Concurrent Collections
Programs that employ several threaded collections must be carefully coded. This is referred to as concurrent programming in general. The Java platform offers significant concurrent programming capability. For further information, see Java Concurrency Utilities. Because collections are used so frequently, the APIs contain a variety of concurrently friendly interfaces and implementations of collections. These types provide properties that are typically required in concurrent programming, going beyond the synchronization wrappers we previously covered.
There are available concurrent-aware interfaces such as:
BlockingQueue
TransferQueue
BlockingDeque
ConcurrentMap
ConcurrentNavigableMap
The following implementation classes support concurrent awareness:
LinkedBlockingQueue
ArrayBlockingQueue
PriorityBlockingQueue
DelayQueue
SynchronousQueue
LinkedBlockingDeque
LinkedTransferQueue
CopyOnWriteArrayList
CopyOnWriteArraySet
ConcurrentSkipListSet
ConcurrentHashMap
ConcurrentSkipListMap
Collections Framework Vs. Collection Interface
Collection Interface and the collections framework are frequently misunderstood. The fundamental interface of the collections framework is the Collection interface. Map and Iterator are two additional interfaces that are part of the framework. Subinterfaces may also exist for these interfaces.
Subinterfaces of the Collection Interface
The Collection interface has subinterfaces that Java classes implement, as was already described. The Collection interface’s subinterfaces contain all of the methods as well.
The Collection Interface’s subinterfaces are listed below:
List Interface
An ordered collection with the ability to add and remove entries like an array is the List interface.
Set Interface
The Set interface enables us to store elements in various sets, much like the mathematical set. It cannot contain elements twice.
Queue Interface
When we want to store and access elements in a First In, First Out manner, we use the queue interface.
Java Map Interface
Key/value pairs can be used to store elements in Java’s Map interface. Keys are specific names that can be used to access a certain map component. Moreover, each key is associated with a single value.
Java Iterator Interface
The Iterator interface in Java offers methods for gaining access to collections’ elements.
Why the Collections Framework?
A variety of directly usable data structures and algorithms are offered by the Java collections framework. There are two key benefits to this:
- These data structures and algorithms can be manually implemented without the need for programming.
- Given how well-optimized the collections framework is, our code will run significantly faster.
Also, we are able to employ a certain data structure for a particular kind of data due to the collections framework. Here are a few use cases of the collection framework in Java:
- We can utilize the Set interface offered by the collections framework if we want our data to be unique.
- With the Map interface, we may store data as key-value pairs.
- Resizable array functionality is offered by the ArrayList class.
Example of ArrayList Class of Collections
Have a look at an example using the ArrayList class from the collections framework before we call this course to a close.
We can make resizable arrays using the ArrayList class. The class implements the interface for lists (which is a subinterface of the Collection interface).
import java.util.ArrayList;
class Main {
public static void main(String[] args){
ArrayList<String> animals = new ArrayList<>();
// Add elements
animals.add(“Dog”);
animals.add(“Cat”);
animals.add(“Horse”);
System.out.println(“ArrayList: ” + animals);
}
}
Output
ArrayList: [Dog, Cat, Horse]
Advantages of Java Collections Framework
A collections framework’s main benefits are:
- Provides data structures and algorithms so you don’t have to develop them yourself, reducing the amount of programming work required.
- Offers high-performance data structure and algorithm implementations to increase performance. Since there are numerous implementations of each interface, programs can be altered by changing their implementation.
- Offering a standard language to send collections back and forth, provides interoperability between unrelated APIs.
- Reduces the time spent learning APIs by requiring you to become familiar with several ad hoc collection APIs.
- Prevents you from having to create ad hoc collections APIs, which lowers the amount of work needed to design and implement APIs.
- Provides a uniform interface for collections and methods to manipulate them, promoting program reuse
Do you want to learn about exception handling in java? Visit our recent blog.
What makes up the collections framework?
Collections Framework: Represent several collection kinds, including sets, lists, and maps. The framework is built on these interfaces.
General-Purpose Implementations: The collection interfaces’ primary implementations.
Legacy Implementations: The collection interfaces were retrofitted to the Vector and Hashtable classes from prior editions.
Special Purpose Implementations: Implementations intended for usage in unique circumstances. These applications exhibit unusual performance traits, usage limitations, or behavior.
Concurrent Implementations: Applications created for heavy concurrency.
Wrapper Implementations: Other implementations could benefit from adding features like synchronization.
Convenience Implementations: “Mini-implementations” of the collection interfaces that are extremely fast.
Abstract Implementation: The collection interfaces are partially implemented to make custom implementations easier.
Algorithms: Static methods that employ collections to accomplish useful tasks, like sorting a list.
Infrastructure: interfaces that give the collection interfaces crucial assistance.
Array Utilities: Utility functions for reference objects and arrays of primitive types. This feature was brought to the Java platform at the same time as the collections framework even though it isn’t technically speaking a part of it and uses some of the same infrastructure.
Data Structures in Java
A collection of data with well defined operations, behaviors, or features is referred to as a data structure. An effective way to store or organize data in computer memory is through the use of data structures.
A drive-in burger shop using that data structure in Java to keep track of customer orders is an example from real life. (Clients keep coming in; they must pick up the proper meal at the payment/collection window.)
Every area of computer science, including computer graphics, operating systems, artificial intelligence, compiler design, and many more, makes considerable use of data structures.
Check out our recent blog to understand data structures in Python.
Why Does Java Need Data Structures?
The complex nature of the applications necessitates the usage of data structures to address a number of issues brought about by the exponential growth of data.
Reasonable Processor Speed: A computer can process more data if its CPU runs at a reasonable speed. The processor might not be able to handle the workload if the data is not appropriately organized into a data structure.
Data Searchable: We’ve all pondered how we’ll ever find what we’re looking for when we take a quick look at a daunting spreadsheet or a long list of data. Because search methods are built right into data structures, we can quickly and easily find what we’re looking for.
Manage a high volume of data requests: A corporation’s clients could appear to make many data requests at once, and if no data structures are in place, this could lead to a server crash. Computers can manage these multiple requests more effectively thanks to data structures.
Linear Data Structures: It is a single level data structure that has all of their elements arranged in a sequential manner.
Non-Linear Data Structures: Data is not arranged sequentially in non-linear data structures, which are multi-level data structures.
Arrays: Groups of data elements of similar types stored in close proximity to one another are called arrays. It is one of the most straightforward data structures, with each data element being randomly accessible via its index number.
Syntax:
dataType var[]; (or)
dataType[] arr;
Example
class Arr
{
public static void main (String[] args)
{
int[] arr;
arr = new int[5];
arr[0] = 1;
arr[1] = 4;
arr[2] = 15;
arr[3] = 21;
arr[4] = 6;
for (int i = 0; i < arr.length; i++)
System.out.println(arr[i]);
}
}
Advantages of Arrays
- Many identical data elements are represented by an array under a single name.
- The index number in arrays can be used to randomly access the elements.
- Arrays allocate memory in contiguous memory areas for each of its elements. As a result, there is no chance that additional memory will be allocated. This avoids memory overflows and array shortages.
- Arrays can be used to build other data structures such linked lists, stacks, queues, trees, and graphs.
Learn to create GUI in java through the fundamentals of Java Swing.
Linked Lists: Similar to the ArrayList, the LinkedList class is a collection that can include a large number of objects of the same type. Each element in this case is a separate object having a data portion and an address component, and they are not all kept in the same place. Each component is referred to as a node, and pointers and addresses are used to connect them.
The Collection framework is found in the java.util package including Linked List.
Syntax:
LinkedList<dataType>var = new LinkedList<dataType>();
Example
import java.util.*;
public class LinkedList{
public static void main(String args[]){
LinkedList<String> ll=new LinkedList<String>();
ll.add(“Mango”);
ll.add(“Apple”);
ll.add(“Banana”);
ll.add(“Orange”);
System.out.println(ll);
}
}
Output
[Mango, Apple, Banana, Orange]
Advantages of Linked List
- It is a dynamic data structure, the linked list. At runtime, the memory can be allocated and released.
- The insertion and deletion functions make it simple to add or remove the node.
- The linked list efficiently utilizes memory. since we are not required to pre-allocate RAM.
- It may be accessed at a given moment without any memory overhead and has an incredibly quick access time.
- Linked lists can be utilized with linear data structures like stacks and queues.
Stack
The Last In First Out (LIFO) data structure known as a stack can be physically implemented as an array or a linked list. It just has one pointer the top, which directs attention to the element at the top of the stack. A new element can only be removed from the stack after being added to it; it is always placed at the top. A stack can be conceptualized as a container in which insertion and deletion are possible from one end, to put it another way.
Syntax
Stack var = new Stack(size)
Example
class Stack {
private int array[];
private int top;
private int limit;
Stack(int size) {
array = new int[size];
limit = size;
top = -1;
}
public void push(int x) {
if (isFull()) {
System.out.println(“Overflow and program terminatedn”);
System.exit(1);
}
System.out.println(“Inserted ” + x);
array[++top] = x;
}
public int pop() {
if (isEmpty()) {
System.out.println(“STACK EMPTY”);
System.exit(1);
}
return array[top–];
}
public int size() {
return top + 1;
}
public Boolean isEmpty() {
return top == -1;
}
public Boolean isFull() {
return top == limit – 1;
}
public void printStack() {
for (int i = 0; i <= top; i++) {
System.out.println(array[i]);
}
}
public static void main(String[] args) {
Stack stack = new Stack(5);
stack.push(10);
stack.push(20);
stack.push(30);
stack.push(40);
stack.pop();
System.out.println(“nAfter popping out”);
stack.printStack();
}
}
Output
Inserted 10
Inserted 20
Inserted 30
Inserted 40
After popping out
10
20
30
Advantages of Stack
- A linked list and an array cannot manage data in a LIFO manner, but a stack can.
- When a function is called, local variables are placed on a stack and are immediately removed after the function returns.
- The stack can be used to control memory allocation and deallocation.
- Since it is less susceptible to corruption, the stack is safer and more trustworthy.
- Variables cannot be resized in the stack.
Get the basic understanding of developing rich client applications in Java through our blog about JavaFX.
Queue
The FIFO (First-In-First-Out) principle, which states that elements are added to the end of the list and subtracted from the beginning, is the basis for the data structure known as a queue.
Syntax
Queue q1 = new LinkedList(); | Queue q2 = new PriorityQueue();
Example
import java.util.LinkedList;
import java.util.Queue;
class Main
{
public static void main(String[] args)
{
Queue<String> queue = new LinkedList<String>();
queue.add(“Orange”);
queue.add(“Banana”);
queue.add(“Mango”);
queue.add(“Pineapple”);
System.out.println(queue.peek());
queue.remove();
queue.remove();
System.out.println(queue.peek());
System.out.println(queue.size());
if (queue.isEmpty()) {
System.out.println(“The queue is empty”);
}
else {
System.out.println(“The queue is not empty”);
}
}
}
Output
Orange
Mango
2
The queue is not empty
Advantages of Queue
The advantage of queues is that they are rapid, adaptable, and able to handle a range of data kinds. In contrast to fixed-length arrays, queues have the potential to be endlessly long.
Graph
A graph is a type of data structure used to store related data, such as a social media platform’s user base. Vertices and edges comprise a graph.The relationship between the entities (such as a person’s friendships) is represented by the edge, while the entity (such as individuals) is represented by the vertex.
Syntax
BaseType <ParameterType> obj = new BaseType <ParameterType>();
Example
class Graph
{
class Edge {
int src, dst; //source and destination
}
int vertices, edges;
Edge[] edge; // store all the edges in an array
Graph(int vertices, int edges) {
this.vertices = vertices;
this.edges = edges;
edge = new Edge[edges];
for(int i = 0; i < edges; i++)
{
edge[i] = new Edge();
}
}
public static void main(String[] args) {
int noVertices = 5;
int noEdges = 8;
Graph g = new Graph(noVertices, noEdges);
g.edge[0].src = 1; // edge 1-2
g.edge[0].dst = 2;
g.edge[1].src = 1; // edge 1-3
g.edge[1].dst = 3;
g.edge[2].src = 1; // edge 1-4
g.edge[2].dst = 4;
g.edge[3].src = 2; // edge 2-4
g.edge[3].dst = 4;
g.edge[4].src = 2; // edge 2-5
g.edge[4].dst = 5;
g.edge[5].src = 3; // edge 3-4
g.edge[5].dst = 4;
g.edge[6].src = 3; // edge 3-5
g.edge[6].dst = 5;
g.edge[7].src = 4; // edge 4-5
g.edge[7].dst = 5;
for(int i = 0; i < noEdges; i++) {
System.out.println(g.edge[i].src + ” – ” + g.edge[i].dst);
}
}
}
Output
1 – 2
1 – 3
1 – 4
2 – 4
2 – 5
3 – 4
3 – 5
4 – 5
Advantages of Graph
The main benefit of a graph data structure is that it makes it possible to use all graph-related computer science techniques. After figuring out how to graph your domain logic, you can use all of the power of graph algorithms to solve your issue.
Gain the fundamental understanding of software testing by checking out our recent blog.
Set
A set is a grouping of distinct items. In order to store different values, Java provides a set interface. To set is an interface found in the java.util package. The Set interface enlarges the Collection interface. An unordered list or collection with no room for duplicates is referred to as a collection interface. It is used to generate the mathematical set. The set interface uses the collection interface’s techniques to stop duplicate elements from being inserted. SortedSet and NavigableSet are two interfaces that enhance the implementation of a set.
Syntax
Set<dataType> set = new HashSet<dataType> ();
Example
import java.util.*;
public class Set{
public static void main(String[] args)
{
Set<String> data = new LinkedHashSet<String>();
data.add(“This”);
data.add(“Is”);
data.add(“Set”);
data.add(“Example”);
System.out.println(data);
}
}
Output
[This, Is, Set, Example]
Advantages of Set
- There can never be a duplicate object in a set.
- Access times of O are often guaranteed using sets (logN).
Map
There is a map interface in Java. The package util represents a key and a value. The Map interface does not have a subclass called Collection. It functions differently from the other collection types as a result. Every map has a unique set of keys.
Syntax
Map hm<dataType,dataType> = new HashMap<dataType,dataType>();
Example
import java.util.*;
public class GFG {
public static void main(String[] args)
{
Map<String, Integer> map = new HashMap<>();
map.put(“Mango”, 10);
map.put(“Apple”, 20);
map.put(“Banana”, 30);
for (Map.Entry<String, Integer> e : map.entrySet())
System.out.println(e.getKey() + ” “
+ e.getValue());
}
}
Output
Apple 20
Mango 10
Banana 30
Advantages of Map
- An array (or, better yet, a vector) is wonderful if all you care about is looking up data, and you know that the keys you’re using to do so fall within a reasonably narrow integer range. Using a key in real-time, you can quickly look something up.
- Items are kept on a map in key order. The objects in a map can then be iterated over from start to finish in sorted key order. You can accomplish this with an array or vector, of course, but as was said before, a map enables you to declare any arbitrary key type and any arbitrary ordering.
- All of the objects in an array or vector must be moved to the left in order to insert in the middle of it. If you have a vector and a dynamic array, you must enlarge the vector to avoid having to copy the entire array to the new memory.
Do you know what the Java Developer Salary for Freshers is? Read through our article.
Working with Collections in Java
Example: Array List
import java.util.*;
class ArrayListExample{
public static void main(String args[]){
ArrayList al=new ArrayList(); // creating array list
al.add(“Tree”); // adding elements
al.add(“Tire”);
Iterator itr=al.iterator();
while(itr.hasNext()){
System.out.println(itr.next());
}
}
}
Output
Tree
Tire
Example: Linked List
import java.util.*;
public class LinkedlistExample{
public static void main(String args[]){
LinkedList<String> al=new LinkedList<String>();// creating linked list
al.add(“Doni”); // adding elements
al.add(“Kohli”);
al.add(“Dawan”);
Iterator<String> itr = al.iterator();
while(itr.hasNext()){
System.out.println(itr.next());
}
}
}
Output
Doni
Kohli
Dawan
Example: Priority Queue
import java.util.*;
class QueueExample {
public static void main(String args[]){
PriorityQueue<String> queue=new PriorityQueue<String>();
// creating priority queue
queue.add(“Doni”);
// adding elements
queue.add(“Kohli”);
queue.add(“Dawan”);
System.out.println(“head:”+queue.element());
System.out.println(“head:”+queue.peek());
System.out.println(“iterating the 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: Doni
head: Doni
iterating the queue elements:
Doni
Kohli
Dawan
after removing two elements:
Dawan
Example: HashSet
import java.util.*;
class HashsetExample{
public static void main(String args[]){
HashSet&amp;amp;lt;String&amp;amp;gt; al=new HashSet(); // creating hashSet
al.add(“Doni”); // adding elements
al.add(“Dawan”);
al.add(“Hardik”);
Iterator&amp;amp;lt;String&amp;amp;gt; itr=al.iterator();
while(itr.hasNext()){
System.out.println(itr.next());
}
}
}
Output
Dawan
Doni
Hardik
Example: Linked Hash Set
import java.util.*;
class LinkedHashsetExample{
public static void main(String args[]){
LinkedHashSet&amp;amp;lt;String&amp;amp;gt; al=new LinkedHashSet(); // creating linkedhashset
al.add(“Doni”); // adding elements
al.add(“Hardik”);
al.add(“Rahane”);
Iterator&amp;amp;lt;String&amp;amp;gt; itr=al.iterator();
while(itr.hasNext()){
System.out.println(itr.next());
}
}
}
}
Output
Doni
Hardik
Rahane
Example: TreeSet
import java.util.*;
class TreeSetExample{
public static void main(String args[]){
TreeSet&amp;amp;lt;String&amp;amp;gt; al=new TreeSet&amp;amp;lt;String&amp;amp;gt;(); // creating treeSet
al.add(“Hardki”); // adding elements
al.add(“Doni”);
al.add(“Rahane”);
Iterator&amp;amp;lt;String&amp;amp;gt; itr=al.iterator();
while(itr.hasNext()){
System.out.println(itr.next());
}
}
}
Output
Hardik
Doni
Rahane
Gain expertise on how to compare two strings in java through our recent article.
Conclusion
Java’s Collection framework offers an architecture for storing and managing a collection of objects. Any data actions, including searching, sorting, insertion, manipulation, and deletion, are possible with Java Collections. A collection in Java is a group of related objects.
In Java, a data structure is a group of data elements that provides a useful way to store and organize data on a computer. Java data structures include arrays, Linked Lists, Stacks, Queues, and Queues.
Hope this article will be useful for you to understand collections framework and data structures in Java with examples. Utilize the excellent practices by enrolling in our Java Training in Chennai at SLA Institute.