Topic 91 of 119 10. Java Collections Framework Interactive Tutorial

Java LinkedList: Doubly-Linked Lists, Queue Operations, and Use Cases

9 mins read Last updated: 22 Aug 2026 30,743 views

Direct Answer & Core Concept

LinkedList is a Java collection class that implements the List and Deque interfaces. Unlike ArrayList, which is based on a resizable array, LinkedList stores elements as linked nodes.

Each node keeps a reference to the element and links to neighboring nodes. In Java, LinkedList is implemented as a doubly-linked list, meaning each node is connected to both the previous and next node.

Because it implements Deque, LinkedList can also be used for queue, double-ended queue, and stack-like operations.

Detailed Explanation & Mechanics

What Is LinkedList in Java?

LinkedList is a class from the java.util package.

Basic example:

Main.java
Run Online
import java.util.LinkedList;
LinkedList<String> names = new LinkedList<>();
names.add("Amit");
names.add("Rahul");
names.add("Priya");
System.out.println(names);

Output:

A LinkedList can dynamically grow as elements are added.


Importing LinkedList

You need to import the class before using it:

Main.java
Run Online
import java.util.LinkedList;

You can also use:

However, importing the specific class makes dependencies clearer.


Creating a LinkedList

The basic syntax is:

Main.java
Run Online
LinkedList<Type> list = new LinkedList<>();

For example:

Main.java
Run Online
LinkedList<String> cities = new LinkedList<>();

An integer list can be created with:

Main.java
Run Online
LinkedList<Integer> numbers = new LinkedList<>();

Remember that Java collections use wrapper classes rather than primitive types such as int.


How LinkedList Works Internally

The key idea behind LinkedList is its node structure.

Conceptually, a doubly-linked list looks like this:

Main.java
Run Online
null↓[Previous | A | Next] ⇄[Previous | B | Next] ⇄[Previous | C | Next]↓null

Each node contains:

  • A reference to the stored element

  • A reference to the previous node

  • A reference to the next node

This allows nodes to be connected in both directions.

Java's LinkedList maintains references to the first and last nodes, which helps with operations at both ends.


Doubly-Linked List Explained

A singly-linked list normally has one direction:

A doubly-linked list has two directions:

The ability to move forward and backward through the nodes is useful for certain insertion, removal, and deque operations.

However, this does not mean every LinkedList operation is automatically faster than ArrayList.


Adding Elements to LinkedList

The simplest operation is:

Example:

Main.java
Run Online
LinkedList<String> fruits = new LinkedList<>();
fruits.add("Apple");
fruits.add("Banana");
fruits.add("Mango");
System.out.println(fruits);

Output:

Elements are added to the end of the list.


Adding an Element at a Specific Position

You can insert an element at an index:

The resulting list becomes:

Main.java
Run Online
[Apple, Orange, Banana, Mango]

The important performance detail is that LinkedList still needs to locate the requested position before inserting there.

Therefore, insertion at an arbitrary index is not automatically O(1).


Adding Elements at the Beginning

LinkedList provides:

Example:

Main.java
Run Online
LinkedList<String> names = new LinkedList<>();
names.add("Rahul");
names.add("Priya");
names.addFirst("Amit");
System.out.println(names);

Output:

This operation can be performed efficiently because the list maintains a reference to its first node.


Adding Elements at the End

You can use:

Example:

Main.java
Run Online
LinkedList<String> names = new LinkedList<>();
names.addLast("Amit");
names.addLast("Rahul");
names.addLast("Priya");
System.out.println(names);

Output:

add() also adds to the end for a normal LinkedList.


Accessing Elements with get()

You can access an element using:

Example:

Main.java
Run Online
LinkedList<String> names = new LinkedList<>();
names.add("Amit");
names.add("Rahul");
names.add("Priya");
System.out.println(names.get(1));

Output:

However, unlike ArrayList, indexed access in a LinkedList is typically O(n).

The list must traverse nodes to reach the requested position.


Why LinkedList Is Slower for Random Access

Consider:

An array-backed ArrayList can typically calculate the location directly.

A linked list has to follow node references until it reaches the required position.

Conceptually:

Main.java
Run Online
Start↓Node 1↓Node 2↓Node 3↓...↓Node 5000

This makes repeated random indexed access inefficient compared with ArrayList.


Updating an Element

You can use:

Example:

Main.java
Run Online
LinkedList<String> names = new LinkedList<>();
names.add("Amit");
names.add("Rahul");
names.add("Priya");
names.set(1, "Rohan");
System.out.println(names);

Output:

The list size does not change.


Removing Elements

You can remove an element by index:

Or remove an object:

Example:

Main.java
Run Online
LinkedList<String> names = new LinkedList<>();
names.add("Amit");
names.add("Rahul");
names.add("Priya");
names.remove("Rahul");
System.out.println(names);

Output:


Removing the First Element

Use:

Example:

Main.java
Run Online
LinkedList<String> queue = new LinkedList<>();
queue.add("A");
queue.add("B");
queue.add("C");
queue.removeFirst();
System.out.println(queue);

Output:

This is useful for queue-style processing.


Removing the Last Element

Use:

Example:

Main.java
Run Online
LinkedList<String> list = new LinkedList<>();
list.add("A");
list.add("B");
list.add("C");
list.removeLast();
System.out.println(list);

Output:


ArrayList vs LinkedList

Both classes implement List, but their underlying structures are different.

FeatureArrayListLinkedList
Main structureResizable arrayDoubly-linked nodes
Indexed get()Typically O(1)Typically O(n)
Add at endAmortized O(1)O(1)
Add at beginningO(n)O(1)
Remove at beginningO(n)O(1)
Random accessExcellentPoor
Memory overheadGenerally lowerGenerally higher
Implements DequeNoYes
Typical list defaultOftenLess often

The complexity of insertion/removal in a linked list needs an important qualification: once the correct node is already known, changing the links can be O(1). Finding an arbitrary position can take O(n).


LinkedList as a Queue

One of the useful features of LinkedList is that it implements Queue.

A queue normally follows FIFO:

For example:

Main.java
Run Online
Customer A → Customer B → Customer C

Customer A is processed first.

You can use:

Main.java
Run Online
Queue<String> queue = new LinkedList<>();

Example:

Main.java
Run Online
import java.util.LinkedList;
import java.util.Queue;
Queue<String> queue = new LinkedList<>();
queue.offer("A");
queue.offer("B");
queue.offer("C");
System.out.println(queue);

Output:


Queue offer(), peek(), and poll()

Three important queue operations are:

offer()

Adds an element to the queue.

peek()

Returns the front element without removing it.

Main.java
Run Online
System.out.println(queue.peek());

poll()

Returns and removes the front element.

Main.java
Run Online
System.out.println(queue.poll());

Example:

Main.java
Run Online
Queue<String> queue = new LinkedList<>();
queue.offer("A");
queue.offer("B");
queue.offer("C");
System.out.println(queue.peek());
System.out.println(queue.poll());
System.out.println(queue);

Output:


Queue Example: Customer Processing

A queue can represent customers waiting for service.

Main.java
Run Online
Queue<String> customers = new LinkedList<>();
customers.offer("Customer 1");
customers.offer("Customer 2");
customers.offer("Customer 3");
while (!customers.isEmpty()) {
    String customer = customers.poll();
    System.out.println("Serving: " + customer);
}

Output:

Main.java
Run Online
Serving: Customer 1Serving: Customer 2Serving: Customer 3

This demonstrates the FIFO principle.


LinkedList as a Deque

Because LinkedList implements Deque, you can add and remove elements from both ends.

Main.java
Run Online
Deque<String> deque = new LinkedList<>();
deque.addFirst("B");
deque.addLast("C");
deque.addFirst("A");
System.out.println(deque);

Output:

A deque is useful when both the front and back of a collection need to be modified.


Important Deque Methods

Some commonly used methods include:

MethodPurpose
addFirst()Add at front
addLast()Add at end
removeFirst()Remove front
removeLast()Remove end
peekFirst()View front
peekLast()View end
offerFirst()Offer at front
offerLast()Offer at end
pollFirst()Remove and return front
pollLast()Remove and return end

Example:

Main.java
Run Online
Deque<Integer> numbers = new LinkedList<>();
numbers.addFirst(20);
numbers.addLast(30);
numbers.addFirst(10);
System.out.println(numbers);

Output:


LinkedList as a Stack

Because Deque supports operations at both ends, a LinkedList can also be used for stack-like behavior.

However, for a normal stack/deque workload, ArrayDeque is generally a better modern choice.

Example:

Main.java
Run Online
Deque<String> stack = new LinkedList<>();
stack.push("A");
stack.push("B");
stack.push("C");
System.out.println(stack.pop());

Output:

This follows:

Main.java
Run Online
LIFOLast In → First Out

ArrayDeque vs LinkedList

Although LinkedList implements Deque, it is not always the best deque implementation.

For many ordinary queue, deque, and stack use cases, ArrayDeque is often preferred because its array-backed structure generally has lower memory overhead and better cache locality.

Example:

Main.java
Run Online
Deque<String> queue = new ArrayDeque<>();

Use LinkedList when its list behavior is useful as well, rather than choosing it simply because it supports queue operations.


LinkedList Performance

Typical complexity characteristics are:

OperationTypical Complexity
get(index)O(n)
set(index, value)O(n)
Add at beginningO(1)
Add at endO(1)
Remove firstO(1)
Remove lastO(1)
SearchO(n)
Insert at arbitrary indexO(n)
Remove at arbitrary indexO(n)

The O(n) complexity for indexed insertion/removal includes the cost of locating the position.

Once a node is already known, changing neighboring links can be performed in constant time.


Why LinkedList Uses More Memory

Each linked-list node needs more than just the stored value.

Conceptually, each node contains:

Main.java
Run Online
+-----------------------------+| Element || Previous node reference || Next node reference |+-----------------------------+

Therefore, a LinkedList has additional per-element memory overhead compared with an array-backed list.

For large collections, this difference can matter.


LinkedList and Null Values

LinkedList allows null elements.

Example:

Main.java
Run Online
LinkedList<String> names = new LinkedList<>();
names.add("Amit");
names.add(null);
names.add("Rahul");
System.out.println(names);

Output:

Whether null should be used depends on the application's design.


LinkedList and Duplicate Elements

Duplicates are allowed.

Main.java
Run Online
LinkedList<String> names = new LinkedList<>();
names.add("Amit");
names.add("Rahul");
names.add("Amit");
System.out.println(names);

Output:

If you need unique values, a Set may be more appropriate.


Checking the Size

Use:

Example:

Main.java
Run Online
LinkedList<String> names = new LinkedList<>();
names.add("Amit");
names.add("Rahul");
System.out.println(names.size());

Output:


Checking Whether the List Is Empty

Use:

Example:

Main.java
Run Online
LinkedList<String> names = new LinkedList<>();
System.out.println(names.isEmpty());

Output:

After adding an element:

Main.java
Run Online
names.add("Amit");
System.out.println(names.isEmpty());

Output:


Searching in LinkedList

You can use:

Example:

Main.java
Run Online
LinkedList<String> languages = new LinkedList<>();
languages.add("Java");
languages.add("Python");
languages.add("C++");
System.out.println(languages.contains("Java"));

Output:

You can also use:

and:

Search operations are typically O(n).


Iterating Through LinkedList

An enhanced for loop is simple:

Main.java
Run Online
for (String name : names) {
    System.out.println(name);
}

You can also use an iterator:

Main.java
Run Online
Iterator<String> iterator = names.iterator();
while (iterator.hasNext()) {
    System.out.println(iterator.next());
}

For bidirectional traversal, LinkedList also supports ListIterator.


ListIterator with LinkedList

ListIterator can move forward and backward.

Main.java
Run Online
LinkedList<String> names = new LinkedList<>();
names.add("Amit");
names.add("Rahul");
names.add("Priya");
ListIterator<String> iterator = names.listIterator();
while (iterator.hasNext()) {
    System.out.println(iterator.next());
}while (iterator.hasPrevious()) {
    System.out.println(iterator.previous());
}

This can be useful when an application needs list traversal in both directions.


Clearing a LinkedList

The clear() method removes all elements.

Main.java
Run Online
LinkedList<String> names = new LinkedList<>();
names.add("Amit");
names.add("Rahul");
names.clear();
System.out.println(names);

Output:


LinkedList with Custom Objects

A LinkedList can store objects of your own classes.

Main.java
Run Online
class Product {
    String name;
    double price;
    Product(String name, double price) {
        this.name = name;
        this.price = price;
    }
}

Create the list:

Main.java
Run Online
LinkedList<Product> products = new LinkedList<>();
products.add(new Product("Laptop", 60000));
products.add(new Product("Mouse", 1000));

Iterate over it:

Main.java
Run Online
for (Product product : products) {
    System.out.println(product.name + " - " + product.price);
}

This pattern is common in business applications.


Programming to the Interface

Instead of:

Main.java
Run Online
LinkedList<String> names = new LinkedList<>();

you can use:

Main.java
Run Online
List<String> names = new LinkedList<>();

when you need list behavior.

If the primary purpose is queue/deque processing:

Main.java
Run Online
Deque<String> queue = new LinkedList<>();

This communicates the intended behavior more clearly.

It also allows the implementation to be changed later with less impact:

Main.java
Run Online
Deque<String> queue = new ArrayDeque<>();

Real-World Use Cases for LinkedList

LinkedList can be useful when an application naturally needs linked-list behavior or when the same structure needs both List and Deque capabilities.

Potential examples include:

1. Frequent Operations at Both Ends

Main.java
Run Online
Deque<String> tasks = new LinkedList<>();
tasks.addFirst("Urgent Task");
tasks.addLast("Normal Task");

2. Bidirectional List Processing

A ListIterator can traverse the collection forward and backward.

3. Small Deque-Based Structures

When you specifically need a deque and also want LinkedList semantics, it can be suitable.

4. Teaching Linked Data Structures

LinkedList is useful for learning how nodes, references, insertion, and removal work.


When LinkedList Is Not a Good Choice

Avoid choosing LinkedList simply because insertion or removal sounds faster.

For example, if your application frequently does:

Main.java
Run Online
list.get(5000);
list.get(9000);
list.get(12000);

an ArrayList is generally better suited to indexed access.

Likewise, if you simply need a queue or stack, consider:

before choosing LinkedList.

The workload should determine the collection.


Common LinkedList Mistakes

Mistake 1: Assuming LinkedList Has Fast Random Access

This:

is not a constant-time operation.

The list must locate the appropriate node.


Mistake 2: Assuming LinkedList Is Always Faster Than ArrayList

The underlying workload matters.

ArrayList can be faster for many real-world workloads because indexed access is constant-time and its contiguous storage can provide good cache locality.


Mistake 3: Using LinkedList as a Queue Without Knowing Queue Methods

Instead of manually managing indexes, use the queue API:

Main.java
Run Online
Queue<String> queue = new LinkedList<>();
queue.offer("A");
queue.offer("B");
String item = queue.poll();

This expresses the FIFO behavior directly.


Mistake 4: Using LinkedList for Every Insertion Problem

Even if insertion/removal can be efficient after reaching a node, locating an arbitrary position can still take O(n).

The actual operation pattern matters.


Complete LinkedList Example

The following example demonstrates list and deque operations:

Main.java
Run Online
import java.util.LinkedList;
public class Main {
    public static void main(String[] args) {
        LinkedList<String> names = new LinkedList<>();
        // Add elements
        names.add("Rahul");
        names.add("Priya");
        names.add("Amit");
        // Add at beginning
        names.addFirst("Rohan");
        // Add at end
        names.addLast("Sneha");
        System.out.println("List: " + names);
        // Access
        System.out.println("First: " + names.getFirst());
        System.out.println("Last: " + names.getLast());
        // Remove first
        names.removeFirst();
        // Remove last
        names.removeLast();
        System.out.println("After removal: " + names);
        // Search
        System.out.println("Contains Amit: " + names.contains("Amit"));
        // Size
        System.out.println("Size: " + names.size());
    }
}

Possible output:

Main.java
Run Online
List:[Rohan, Rahul, Priya, Amit, Sneha]First: RohanLast: SnehaAfter removal:[Rahul, Priya, Amit]Contains Amit: trueSize: 3

Queue Example Using LinkedList

Main.java
Run Online
import java.util.LinkedList;
import java.util.Queue;
public class Main {
    public static void main(String[] args) {
        Queue<String> queue = new LinkedList<>();
        queue.offer("Task 1");
        queue.offer("Task 2");
        queue.offer("Task 3");
        while (!queue.isEmpty()) {
            String task = queue.poll();
            System.out.println("Processing: " + task);
        }
    }
}

Output:

Main.java
Run Online
Processing: Task 1Processing: Task 2Processing: Task 3

This demonstrates FIFO processing.


LinkedList Quick Revision

ConceptKey Point
Packagejava.util
Main structureDoubly-linked nodes
InterfacesList, Deque, Queue indirectly
Duplicate valuesAllowed
nullAllowed
Indexed accessTypically O(n)
Add firstO(1)
Add lastO(1)
Remove firstO(1)
Remove lastO(1)
SearchO(n)
Random accessPoor compared with ArrayList
Memory overheadHigher than array-backed lists
Queue supportYes
Deque supportYes

Frequently Asked Questions

What is LinkedList in Java?

LinkedList is a collection class in the java.util package that implements a doubly-linked list and also provides List and Deque functionality.

Is Java LinkedList a doubly-linked list?

Yes. Java's LinkedList is implemented as a doubly-linked list.

What is the difference between ArrayList and LinkedList?

ArrayList uses a resizable array and provides fast indexed access. LinkedList uses linked nodes and provides efficient operations at its ends, but indexed access is typically O(n).

Is LinkedList faster than ArrayList?

Not generally. The answer depends on the workload. ArrayList is often preferable for indexed access and many general-purpose list workloads.

Can LinkedList be used as a queue?

Yes. It implements Deque, which extends Queue.

Example:

Main.java
Run Online
Queue<String> queue = new LinkedList<>();

Can LinkedList be used as a stack?

Yes, it can provide stack-like operations through Deque. However, ArrayDeque is generally preferred for ordinary stack/deque use cases.

Does LinkedList allow duplicate values?

Yes. Multiple equal elements can be stored.

Does LinkedList allow null?

Yes. A LinkedList can contain null.

Why does LinkedList use more memory?

Each node needs references to the previous and next nodes in addition to the stored element.

What is the time complexity of get() in LinkedList?

Indexed get() is typically O(n), because the list may need to traverse nodes to reach the requested position.

When should I use LinkedList?

Use it when its deque/list behavior fits the workload, particularly when operations at the ends are important. For many ordinary lists, ArrayList is often a better default.

Graphics and Design Ideas

1. Doubly-Linked List Diagram

Show the structure visually:

Architecture Diagram
null
↓
┌──────────────┐     ┌──────────────┐     ┌──────────────┐
│ prev |  A | next │ ⇄ │ prev | B | next │ ⇄ │ prev | C | next │
└──────────────┘     └──────────────┘     └──────────────┘
 ↑                                                   ↑
First                                               Last

Use arrows in both directions to make the concept of a doubly-linked list clear.


2. ArrayList vs LinkedList Graphic

Create a side-by-side comparison:

Main.java
Run Online
ArrayList[ A][ B][ C][ D][ E] Array Storage Fast Index AccessLinkedList[A] ⇄[B] ⇄[C] ⇄[D] ⇄[E] Linked Nodes Sequential Traversal

3. FIFO Queue Graphic

Show:

Main.java
Run Online
FIFOIncoming↓[A] →[B] →[C] →[D] ↑Front Rear

Then show poll() removing A.


4. Deque Graphic

Illustrate operations from both ends:

Architecture Diagram
addFirst()
↓
┌────┬────┬────┬────┐
         │ A  │ B  │ C  │ D  │
         └────┴────┴────┴────┘
                              ↑
                         addLast()

removeFirst() ←          → removeLast()

5. Performance Comparison Chart

Create a visual table:

Main.java
Run Online
Operation ArrayList LinkedListget(index) O(1) O(n)add(end) O(1)* O(1)add(beginning) O(n) O(1)remove(beginning) O(n) O(1)search O(n) O(n)

Add a note:

* Amortized complexity.


6. Real-World Use Case Graphic

Create four cards:

Queue
Customer service processing

Deque
Add/remove from both ends

Bidirectional Traversal
Forward and backward navigation

Linked Data Structure Learning
Understanding nodes and references

Runnable Code Example: Java LinkedList

Java 17+
Main.java
Run Online
import java.util.LinkedList;
import java.util.Deque;
public class LinkedListDemo {
    public static void main(String[] args) {
        Deque<String> queue = new LinkedList<>();
        queue.offer("Task 1");
        queue.offer("Task 2");
        queue.offer("Task 3");
        System.out.println("Polled from queue: " + queue.poll());
        // Task 1
        System.out.println("Remaining queue: " + queue);
    }
}

Common Java Technical Interview Questions & Answers

Interview Prep
Q1

Why is ArrayList generally preferred over LinkedList even for insertions?

Because modern CPU architectures excel at contiguous memory cache-line fetching (ArrayList), while node pointers in LinkedList cause frequent CPU cache misses.
Q2

What is the preferred alternative to LinkedList for queues and stacks?

ArrayDeque is faster, has lower memory overhead, and does not generate garbage Node objects.

Key Takeaways, Best Practices & Clean Code Rules

Java Best Practice & Production Rules

Use ArrayDeque instead of LinkedList when implementing Stacks and Queues for faster execution and lower memory footprint.