LinkedList in Java
In Java programming and software development, choosing the correct data structure can
majorly impact the performance and efficiency of any program or application. The LinkedList in
Java is a very useful data structure that generally allows efficient insertions and deletions, which
makes it ideal for memory management, real-time Java applications, and undo operations in
different text editors.
With this Java LinkedList tutorial, you are going to learn types of LinkedList, operations, working,
methods, and many more. Whether you are just getting started with Java Data Structures or you
are a proficient Java programmer, this tutorial on Java LinkedLists will help you gain the required
knowledge to implement and use these linked lists effectively in your Java Coding Problems.
What is a LinkedList in Java?
A LinkedList in Java is generally a linear data structure that is used to store a collection of
elements where each element which is called a node is linked to the next element using a
pointer. This dynamic data structure is very useful in various operations like insertion,
deletion, and traversal of elements making it very important in programming and
Core Concept of LinkedLists
Imagine a train where each compartment (node) is connected to the next one through a
coupling (pointer/reference). This is similar to how a linked list works:
Each node stores data (like passengers in a train compartment).
Each node also has a pointer that connects it to the next node (like the coupling between
compartments).
The last node points to null, indicating the end of the list.
Unlike arrays, which use indexes for direct access, a linked list requires traversal from the first
node to reach a specific element.
Key Differences Between LinkedLists and Array
Advantages of LinkedList Over Array
Dynamic Size: In the LinkedList, you don’t need to define the size at the time of creation as it can
grow or shrink based on the requirement.
Efficient Insertions and Deletions: The addition or removal of elements in Java LinkedList does
not require to shift of the other elements.
Better Memory Utilization: It only uses the memory required for the current elements.
Working of LinkedList in Java
Now that you’ve seen the various kinds of LinkedLists there are in , let us understand how it
actually works internally. A LinkedList operates differently from an array, as it generally offers
dynamic allocation of memory, efficient insertion and deletion, and adaptive data handling.
1. How LinkedList Stores Data
A LinkedList in Java is normally defined by the number of nodes, whereby each node has two
elements:
Data that contains the actual value.
Pointer (Reference) that simply Stores the memory address of the next node.
2. Memory Allocation in LinkedList
Unlike , which generally have contiguous memory allocation, a LinkedList typically uses non-
contiguous memory allocation which means that nodes are simply scattered across memory but
are linked together through references.
3. How Memory is Allocated in a LinkedList?
When a new node is created, Java dynamically allocates memory for it.
Each node of the LinkedList generally stores the memory address(reference) of the next node,
unlike the arrays where it is stored in a continuous memory block.
Garbage Collector in Java automatically deallocates memory for the unused nodes and prevents
memory leaks.
4. Comparison of Memory Representation between LinkedList vs Array
5. Example: Dynamic Memory Allocation in a LinkedList
class Node {
int data;
Node next;
public Node(int data) {
this.data = data;
this.next = null; // Initially, the node points to NULL
public class LinkedListMemoryDemo {
public static void main(String[] args) {
Node head = new Node(10); // Allocates memory dynamically
head.next = new Node(20); // Creates another node and links it
head.next.next = new Node(30); // Continues the linking process
Node temp = head;
while (temp != null) {
System.out.println("Data: " + temp.data + ", Address: " + temp);
temp = temp.next;
}
Output Example (Addresses will vary after every execution):
This output shows that nodes in the LinkedList are stored at different memory locations but are
connected through references.
How to Create a Custom LinkedList in Java
While Java generally provides the built-in LinkedList class in its Java Collections Framework (JCF),
creating a custom implementation of LinkedList simply helps in understanding how LinkedLists
manage data, memory, and pointers.
1. Creating the Node Class
Let’s define a Node class for creating a custom linked list to represent each node in our Singly
LinkedList.
// Node class representing a single element in the LinkedList
class Node {
int data; // Stores the value of the node
Node next; // Stores the reference to the next node
// Constructor to initialize the node with a value
public Node(int data) {
this.data = data;
this.next = null; // Initially, the next reference is set to null
2. Creating a Custom LinkedList Class
Now, we need a class that can manage the list. The class must have:
A reference back to the head node (list starting node).
Methods to add elements to the list.
A method to iterate over and display the list.
Let’s define the CustomLinkedList class:
// Node class representing a single element in the LinkedList
class Node {
int data; // Stores the value of the node
Node next; // Stores the reference to the next node
// Constructor to initialize the node with a value
public Node(int data) {
this.data = data;
this.next = null; // Initially, the next reference is set to null
// Custom implementation of a Singly LinkedList
class CustomLinkedList {
Node head; // Head node of the list
// Method to add a new node at the end of the list
public void add(int data) {
Node newNode = new Node(data); // Create a new node
// If the list is empty, set the new node as the head
if (head == null) {
head = newNode;
return;
}
// Traverse to the last node
Node temp = head;
while (temp.next != null) {
temp = temp.next;
// Link the last node to the new node
temp.next = newNode;
}
// Method to display the LinkedList elements
public void display() {
Node temp = head;
// If the list is empty
if (temp == null) {
System.out.println("LinkedList is empty.");
return;
// Traverse and print each node
while (temp != null) {
System.out.print(temp.data + " -> ");
temp = temp.next;
System.out.println("NULL");
// Main class to test the LinkedList implementation
public class LinkedListDemo {
public static void main(String[] args) {
CustomLinkedList list = new CustomLinkedList();
// Adding elements to the linked list
list.add(10);
list.add(20);
list.add(30);
list.add(40);
// Displaying the linked list
list.display();
Output:
3. Explanation of Code
The Node class in it generally defines the individual elements of the LinkedList.
The class names as CustomLinkedList typically manage the list with its internal head pointer.
To insert the new node at the end, the add() method is being used.
To print the whole custom linked list and display it on the screen, the display() method is used.
The main method (LinkedListDemo) creates a list, adds elements, and prints the list.
Types of LinkedLists in Java
Now that you have learned the basic concepts about the LinkedList and its advantages, let’s
learn its different types in Java. There are three types of LinkedLists in Java:
1. Singly LinkedList in Java
A Singly LinkedList is the simplest form of a linked list where:
Each node contains data, as well as a pointer to the next node.
The last node of the singly linked list points to NULL, which simply indicates the end of the Java
Singly LinkedList.
The starting Node is generally called as head and the last node is called as Tail.
1.1 Structure of a Singly LinkedList
Here, each node simply stores a value and a reference to the next node in the sequence.
1.2 When to Use a Singly LinkedList?
You can use the Singly LinkedList whenever you want to create a simple and lightweight linked
list.
You can use it whenever operations like insertions and deletion at the starting are frequent.
You can also use Singly LinkedList when memory optimization is a top priority (since it stores
only one pointer per node).
1.3 Implementing a Singly LinkedList in Java
class Node {
int data;
Node next;
public Node(int data) {
this.data = data;
this.next = null;
public class SinglyLinkedList {
Node head;
// Insert a new node at the end
public void add(int data) {
Node newNode = new Node(data);
if (head == null) {
head = newNode;
return;
Node temp = head;
while (temp.next != null) {
temp = temp.next;
temp.next = newNode;
}
// Display the linked list
public void display() {
Node temp = head;
while (temp != null) {
System.out.print(temp.data + "-> ");
temp = temp.next;
System.out.println("NULL");
public static void main(String[] args) {
SinglyLinkedList list = new SinglyLinkedList();
list.add(10);
list.add(20);
list.add(30);
list.display();
Output:
2. Doubly LinkedList in Java
Each node in DLL typically contains data, a pointer to the next node, and a pointer to the
previous node. Also, note that the previous pointer of the first node and the next pointer of the
last node are NULL in DLL.
2.1 Structure of a Doubly LinkedList
Here, every node has basically two pointers, one is pointing to the next node, and another
pointing to its previous one.
2.2 When to Use a Doubly LinkedList?
Doubly LinkedList in Java is majorly used in the case of bidirectional traversals.
You can use DLL when you frequently insert or delete elements from both ends.
You can also use DLL when the ability to move backward through the list is useful.
2.3 Implementing a Doubly LinkedList in Java
class DoublyNode {
int data;
DoublyNode next;
DoublyNode prev;
public DoublyNode(int data) {
this.data = data;
this.next = null;
this.prev = null;
public class DoublyLinkedList {
DoublyNode head;
// Insert at the end
public void add(int data) {
DoublyNode newNode = new DoublyNode(data);
if (head == null) {
head = newNode;
return;
DoublyNode temp = head;
while (temp.next != null) {
temp = temp.next;
}
temp.next = newNode;
newNode.prev = temp;
// Display the linked list forward
public void display() {
DoublyNode temp = head;
while (temp != null) {
System.out.print(temp.data + " ");
temp = temp.next;
System.out.println("NULL");
public static void main(String[] args) {
DoublyLinkedList list = new DoublyLinkedList();
list.add(10);
list.add(20);
list.add(30);
list.display();
Output:
3. Circular LinkedList in Java
A Circular LinkedList (CLL) in Java is a variation of a normal linked list in which the last node
simply points back to the first node, which generally forms a circular structure.
In the case of a Singly Circular LinkedList, the next pointer of the last node generally points to
the first node.
In a Doubly Circular LinkedList, both the first and last nodes are connected in both directions.
3.1 Structure of a Singly Circular LinkedList
3.2 Structure of a Doubly Circular LinkedList
3.3 When to Use a Circular LinkedList?
When you are dealing with circular buffer implementations such as CPU scheduling, and
network buffering.
‘When you need to continuously rotate through the elements such as multiplayer games, and
streaming applications.
3.4 Implementing a Circular LinkedList in Java
class CircularNode {
int data;
CircularNode next;
public CircularNode(int data) {
this.data = data;
this.next = null;
public class CircularLinkedList {
CircularNode head, tail;
// Insert a new node
public void add(int data) {
CircularNode newNode = new CircularNode(data);
if (head == null) {
head = newNode;
tail = newNode;
tail.next = head; // Circular reference
return;
tail.next = newNode;
tail = newNode;
tail.next = head; // Maintain circular link
// Display the circular linked list
public void display() {
if (head == null) return;
CircularNode temp = head;
do {
System.out.print(temp.data + " -> ");
temp = temp.next;
} while (temp != head);
System.out.println("(Back to Head)");
public static void main(String[] args) {
CircularLinkedList list = new CircularLinkedList();
list.add(10);
list.add(20);
list.add(30);
list.display();
}
}
Output:
LinkedList Operations in Java
LinkedList operations are very important for managing dynamic data structures efficiently and in
this section, you are going to learn some operations you can perform on LinkedLists.
1. Inserting Elements in Java LinkedList
A linked list in Java stores every element as nodes and is connected with each other by pointer
references. Here, we have explained every step to insert the elements in the Java LinkedList.
You just have to go through all the comments for a deeper understanding.
For every operation, we have written the core methods to perform the specific operations. If
you want to test these operations by running them yourself, we have written the runnable code
performing all the operations at the end of this section
1.1 How to Insert an Element at the beginning of a LinkedList in Java?
For inserting the elements or nodes in a linked list in Java, you just need to follow these steps:
Create a new node with your data
Point the new node you want to insert in LinkedList to the current head
And Update the head to point it to the new node which will simply make it the first element.
Example:
// Insert at the beginning
public void insertAtBeginning(int data) {
Node newNode = new Node(data);
newNode.next = head;
head = newNode;
1.2 How to Insert an Element at the End of a LinkedList in Java?
Now, let’s insert the node(element) at the tail or end of the linked list:
First, create the new node using the given data.
Then traverse the linked list all to the last node whose next is null
And then make that next null to that new node you want to insert.
Example:
// Insert at the end
public void insertAtEnd(int data) {
Node newNode = new Node(data);
if (head == null) {
head = newNode;
return;
Node current = head;
while (current.next != null) {
current = current.next;
current.next = newNode;
1.3 How to Insert an Element at a Specific Position of LinkedList in Java?
To insert the node(element) at any specific position of the linked list:
First, create the new node using the given data.
Traverse the linked list to find the node before you want to insert the new node.
Update the reference of the index-1 node to the new node
Example:
// Insert at a specific position
public void insertAtPosition(int data, int position) {
Node newNode = new Node(data);
if (position == 0) {
newNode.next = head;
head = newNode;
return;
Node current = head;
for (int i = 0; current != null && i < position - 1; i++) {
current = current.next;
}
if (current == null) return;
newNode.next = current.next;
current.next = newNode;
2. How to Update the Value of an Element in a LinkedList?
To update the value of the node, you need to traverse the list until we find the node at a specific
position and replace it with the new reference.
Example:
// Update a node's value at a specific position
public void updateNode(int position, int newData) {
Node current = head;
int currentPosition = 0;
while (current != null) {
if (currentPosition == position) {
current.data = newData;
return;
current = current.next;
currentPosition++;
3. Deleting Elements of LinkedList
Deleting any element from the LinkedList means changing or updating the references of the
adjacent nodes simply removes the reference from the particular node that you to delete.
1. Deleting the First Node
Removing the first node or head node from the LinkedList simply means shifting the head to the
next node in the list.
Example:
// Delete the first node in the LinkedList
public void deleteFirst() {
if (head == null) return; // If list is empty, do nothing
head = head.next; // Move head to the next node
4. Deleting the Last Node
In order to delete the last node of the LinkedList you just need to traverse to the second last of
the list and just update its next pointer to null.
Example:
// Delete the last node in the LinkedList
public void deleteLast() {
if (head == null) return; // If list is empty, do nothing
if (head.next == null) { // If only one node exists
head = null;
return;
Node temp = head;
while (temp.next.next != null) { // Traverse to second last node
temp = temp.next;
temp.next = null; // Remove reference to last node
}
5. Deleting a Node at a Specific Position
For deleting the node of random or any specific position of a given index, you need to traverse
the node just one index position before the given index and update its pointer
Example:
// Delete a node at a given position
public void deleteAtPosition(int position) {
if (head == null) return; // If list is empty, do nothing
if (position == 0) { // If deleting the first node
head = head.next;
return;
Node temp = head;
for (int i = 0; temp != null && i < position - 1; i++) {
temp = temp.next;
if (temp == null || temp.next == null) {
System.out.println("Invalid position");
return;
temp.next = temp.next.next; // Remove the node
Here we have included all the operations to perform on the LinkedList. Try running the code,
and modify it according to your needs in order to learn these operations better.
Example:
// Node class representing each node in the linked list
class Node {
int data;
Node next;
// Constructor to create a new node
Node(int data) {
this.data = data;
this.next = null;
// LinkedList class containing all operations
class LinkedList {
private Node head; // Head of the list
// Insert at the beginning
public void insertAtBeginning(int data) {
Node newNode = new Node(data);
newNode.next = head;
head = newNode;
// Insert at the end
public void insertAtEnd(int data) {
Node newNode = new Node(data);
if (head == null) {
head = newNode;
return;
}
Node current = head;
while (current.next != null) {
current = current.next;
current.next = newNode;
}
// Insert at a specific position
public void insertAtPosition(int data, int position) {
Node newNode = new Node(data);
if (position == 0) {
newNode.next = head;
head = newNode;
return;
Node current = head;
for (int i = 0; current != null && i < position - 1; i++) {
current = current.next;
if (current == null) return;
newNode.next = current.next;
current.next = newNode;
// Update a node's value at a specific position
public void updateNode(int position, int newData) {
Node current = head;
int currentPosition = 0;
while (current != null) {
if (currentPosition == position) {
current.data = newData;
return;
}
current = current.next;
currentPosition++;
// Delete the first node
public void deleteFirst() {
if (head == null) return;
head = head.next;
// Delete the last node
public void deleteLast() {
if (head == null || head.next == null) {
head = null;
return;
Node current = head;
while (current.next.next != null) {
current = current.next;
current.next = null;
// Delete a node at a specific position
public void deleteAtPosition(int position) {
if (head == null) return;
if (position == 0) {
head = head.next;
return;
Node current = head;
for (int i = 0; current != null && i ");
current = current.next;
System.out.println("null");
// Main class to test all LinkedList operations
public class Main {
public static void main(String[] args) {
LinkedList list = new LinkedList();
// Insert operations
list.insertAtBeginning(3);
list.insertAtBeginning(2);
list.insertAtBeginning(1);
list.insertAtEnd(4);
list.insertAtPosition(5, 2);
System.out.println("LinkedList after insertions:");
list.printList(); // Output: 1 -> 2 -> 5 -> 3 -> 4 -> null
// Update operation
list.updateNode(2, 10);
System.out.println("After updating position 2:");
list.printList(); // Output: 1 -> 2 -> 10 -> 3 -> 4 -> null
// Delete operations
list.deleteFirst();
System.out.println("After deleting first node:");
list.printList(); // Output: 2 -> 10 -> 3 -> 4 -> null
list.deleteLast();
System.out.println("After deleting last node:");
list.printList(); // Output: 2 -> 10 -> 3 -> null
list.deleteAtPosition(1);
System.out.println("After deleting node at position 1:");
list.printList(); // Output: 2 -> 3 -> null
Output: