Data Structures in Java Explained with Examples

data-structures-in-java

Data structures are at the heart of good programing in Java. They offer mechanisms to structure, store, and shape data such that applications can be written in ways that it operates correctly, scale appropriately, is easy to modify or maintain. Java comes with of lot of data structures provided with the built-in Collections Framework, and sometimes these are not enough and we need to come up within our own custom solutions. It is very crucial for any Java programmer to be able to understand and learn these data structures due to the fact that there are several of these you encounter pretty much on a daily basis. Starting with plain arrays, Java’s data structures also include trees and hash-based collections, and serve as the foundation for many other types of data-related activities. In this tutorial, we will introduce some of the most important data structures in Java and show you how they function through practical exercises.

Arrays in Java

Arrays are the simplest and most widely used data structure in Java. They retain a list of elements denoted by the same type of value. Arrays are good when we know the size of array in advance and random access is required. It is very efficient to access elements by their index, since arrays are a contiguous block of memory. But they are fixed in size, so that once you make them they do not grow or shrink. In Java, you make an array by indicating its type and desired size, as in int[] numbers = new int[5];. You can then simply assign it values: result[0] = b or use the array for test setup. For example:

int[] values = {10, 20, 30, 40};

System.out.println(values[2]); // Output: 30

Arrays That being said, arrays are used a great deal beneath the surface in other data structures and they provide an integral part of Java’s memory model.

ArrayList: A Dynamic Array Structure

ArrayList is used internally as a dynamic-dynamic array, which means that its size fluctuates at runtime according to the data stored in it. Unlike arrays, an ArrayList can resize itself when a new element is added. This is very flexible and should be used if the set of elements change over time (as most real-world cases). The ArrayLists maintain the order of insertion and allow fast access by index. It is efficient to add or remove elements at the end; other positions may require since elements to be shifted. An ArrayList is created and utilized in the following way:

import java.util.ArrayList;

ArrayList<String> names = new ArrayList<>();

names.add(“Alice”);

names.add(“Bob”);

System.out.println(names.get(1)); // Output: Bob

ArrayList belongs to the Java Collections Framework, and so is that it can be used to replace arrays when a more versatile and convenient option is desired.

LinkedList in Java

A LinkedList is a dynamic data structure represented as a doubly linked list, each node having constant overhead and storing a value, the addresses of previous and next nodes. This structure is extremely efficient for insertion and deletion, especially at the head or middle of a list; no element movement is required. But Access time of LinkedList is slower than ArrayList as it needs to iterate through nodes If you subscribe to our blog and like the articles, do follow us on social media (icons in the footer) 6. Java’s LinkedList works as a queue (FIFO) and can be used in practice to work like stack (LIFO) or Double-ended Queue. Example usage:

import java.util.LinkedList;

LinkedList<Integer> queue = new LinkedList<>();

queue.add(10);

queue.add(20);

queue.addFirst(5);

System.out.println(queue); // Output: [5, 10, 20]

LinkedList are useful for situations that require very frequent inserts and deletes, such as queues or pipelines of real-time processing engines.

HashMap for Key–Value Storage

HashMap is one of the most powerful data structures in Java. It uses key-value storage format and attains average constant time performance for insertion, deletion and look-up functionalities. There are lots of ways to avoid using HashMap if you don’t need it, everywhere the same checks multiplied by number of coders;).HashMaps makes sense for fast access to data with some unique key in all other pieces. It is a question of what this key will be… Internally, the HashMap uses hash code to determine which bucket to use for storage and retrieval can be done very effectively. A simple illustration can be used to demonstrate its applicability:

import java.util.HashMap;

HashMap<String, Integer> ageMap = new HashMap<>();

ageMap.put(“Alice”, 25);

ageMap.put(“Bob”, 30);

System.out.println(ageMap.get(“Alice”)); // Output: 25

HashMap is not ordered, and permits one null key and multiple null values. Other structures, such as LinkedHashMap or TreeMap are more suitable if the order matter.

TreeMap and Sorted Data Storage

A TreeMap is a type of binary search tree used to store key–value pairs in sorted form based on the keys. It is implemented internally using a Red-Black tree, which is again a self-balancing binary search tree. Which means searching, insertion and deletion take O(log n) time. TreeMap is good when you want a sorted dictionary, or you need things like the lowest key etc. Example usage:

import java.util.TreeMap;

TreeMap<Integer, String> grades = new TreeMap<>();

grades.put(90, “A”);

grades.put(80, “B”);

grades.put(70, “C”);

System.out.println(grades.firstEntry()); // Output: 70=C

TreeMap is order secure and so useful when you have to design structures for navigation of menus, scoreboards etc.

HashSet for Unique Element Storage

HashSet is used when you want to store a unique element with no duplicate elements. It internally uses a HashMap to store the elements, so all these operations are done in fast O(1) time. There is no order in HashSet, the elements are displayed in a random way. For example:

import java.util.HashSet;

HashSet<String> countries = new HashSet<>();

countries.add(“USA”);

countries.add(“Canada”);

countries.add(“USA”); 

System.out.println(countries.size()); // Output: 2

HashSet is suitable for use cases such as duplicate filtering, search indexing, visited nodes tracking and membership testing.

Stack and the LIFO Principle

Stack is LIFO based data structure, in which last element added will be removed first. Historically Java had the Stack class, however Modern Java assumes you use Deque implementations like ArrayDeque as they have faster performance. Quotes are applied to things like undo/redo functionality, expression evaluation, parsing and depth-first search. A simple example with Stack:

import java.util.Stack;

Stack<Integer> stack = new Stack<>();

stack.push(10);

stack.push(20);

System.out.println(stack.pop()); // Output: 20

The behavior is instinctive—push something on, pop it off.

 

Read Also : Software QA Explained: How It Works in Practice

 

Queue and the FIFO Structure

Queue is a FIFO (First-In-First-Out) data structure in which the element added first out of all the elements is removed first. Java has several queue implementation such as LinkedList and PriorityQueue. Queues are used extensively in scheduling systems, processing pipelines, thread management and breadth-first searches. Example with LinkedList queue:

import java.util.Queue;

import java.util.LinkedList;

Queue<String> tasks = new LinkedList<>();

tasks.add(“Task1”);

tasks.add(“Task2”);

System.out.println(tasks.poll()); // Output: Task1

Queues provide fair and ordered processing, thereby applicable for real-time communications.

PriorityQueue for Ordered Processing

A PriorityQueue is a queue but not just any sort of sequence, one where elements are dequeued by priority rather than order added. Internally, it is implemented using a heap data structure which gives access to the smallest (in the case of min heap) element in constant time. Elements have to be comparable or you have to provide a Comparator. Example:

import java.util.PriorityQueue;

PriorityQueue<Integer> pq = new PriorityQueue<>();

pq.add(30);

pq.add(10);

pq.add(20);

System.out.println(pq.poll()); // Output: 10

PriorityQueue has multiple applications such as in simulations, event scheduling, shortest path algorithms and system task which has higher priority gets executed first.

Trees and Custom Data Structures

While Java supports tree structures such as TreeMap and TreeSet, programmers may develop their own customized trees, e.g., binary trees, AVL-trees or tries for specific applications. The following simplistic binary tree illustrates how the nodes are worked:

class Node {

    int value;

    Node left, right;

    Node(int value) { this.value = value; }

}

Node root = new Node(10);

root.left = new Node(5);

root.right = new Node(15);

With custom trees developers can create high-performance search engines, directory structures or memory-efficient hierarchical models.

The Importance of Choosing the Correct Data Structure

The choice of your data structure can influence the performance of an application greatly. If you’re inserting in the middle of the list a lot, then an ArrayList instead of a LinkedList can be slow. Prefer HashMap to TreeMap when you don’t care about ordering, it is faster. The choice of PriorityQueue over a normal queue means we are processing elements in the right order! In other words, it is important to know how each data structure performs in terms of time complexity, memory usage, and ordering rules because this knowledge guides you to write neat, better and optimised code.

Conclusion

According to picktechinnovations, Java data structures are a fundamental part of the language and it is important for every developer to know the ins and outs in most situations. Each type of data structure, ranging from simple arrays to contributory linked lists to hashed collections to trees, enjoys a certain discipline that efficiently solves problems. These structures are also simplified in Java’s Collections Framework, although their introduction inspired developers to design new solutions to specific problems. With expertise in using these data structures and a bit of practice through real examples, developers are better prepared to write good software that’s efficient and flexible.