← Back to Home

LinkedList

LinkedList is a doubly linked list implementation of the List and Deque interfaces in the Java Collections Framework. It is optimized for frequent insertions and deletions, making it suitable for dynamic data manipulation scenarios. This is a high-frequency interview topic, especially when compared with ArrayList.

What Is LinkedList?

  • Doubly linked list implementation
  • Maintains insertion order
  • Allows duplicate elements
  • Allows multiple null values
  • Implements List and Deque
  • Part of java.util package
LinkedList<String> list = new LinkedList<>();
          

Position in Collection Hierarchy

Iterable
   └── Collection
        └── List
             └── LinkedList
        └── Deque
             └── LinkedList
          

Key Characteristics of LinkedList

  • Elements stored as nodes (data + prev + next)
  • No shifting of elements
  • Slower random access
  • Faster insertion/deletion

How LinkedList Works Internally (Interview Favorite)

Each node contains:

  • Data
  • Reference to previous node
  • Reference to next node
prev ← [data] → next
          
  • ✔ Efficient insertion and removal
  • ✔ Extra memory overhead for pointers

Creating a LinkedList

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

Commonly Used LinkedList Methods

Adding Elements

list.add(10);
list.addFirst(5);
list.addLast(20);
          

Removing Elements

list.remove();        // first element
list.removeFirst();
list.removeLast();
          

Accessing Elements

list.get(0);
list.getFirst();
list.getLast();
          

Queue / Deque Operations

list.offer(30);
list.poll();
list.peek();
          

✔ Supports FIFO and LIFO operations

Iterating a LinkedList

for (Integer i : list) {
    System.out.println(i);
}
          

Performance Complexity (Important)

Operation Time Complexity
get(index) O(n)
add/remove (beginning) O(1)
add/remove (middle) O(n)
search O(n)

LinkedList vs ArrayList (Key Interview Comparison)

Aspect LinkedList ArrayList
Internal structure Doubly linked list Dynamic array
Random access Slow Fast
Insertion/deletion Fast Slow (middle)
Memory usage Higher Lower
Use case Frequent modifications Frequent reads

Thread Safety

  • Not synchronized
  • Not thread-safe

Thread-safe alternatives: Collections.synchronizedList(), ConcurrentLinkedDeque

When to Use LinkedList

  • Frequent insertions/deletions
  • Implementing stack, queue, deque
  • Data size changes frequently
  • Sequential access patterns

When NOT to Use LinkedList

  • Heavy random access
  • Memory-constrained environments
  • Large datasets with frequent reads

Common Beginner Mistakes

  • Using LinkedList for random access
  • Assuming faster in all cases
  • Ignoring memory overhead
  • Using it like an ArrayList
  • Concurrent modification without care

LinkedList Examples

1. Creating a LinkedList

import java.util.*;

class Demo {
    public static void main(String[] args) {
        LinkedList<String> list = new LinkedList<>();
        list.add("Java");
        list.add("Selenium");
        System.out.println(list);
    }
}
          

Output

[Java, Selenium]
          

2. LinkedList Allows Duplicates

import java.util.*;

class Demo {
    public static void main(String[] args) {
        LinkedList<Integer> list = new LinkedList<>();
        list.add(10);
        list.add(10);
        System.out.println(list);
    }
}
          

Output

[10, 10]
          

3. Maintains Insertion Order

import java.util.*;

class Demo {
    public static void main(String[] args) {
        LinkedList<Integer> list = new LinkedList<>();
        list.add(3);
        list.add(1);
        list.add(2);
        System.out.println(list);
    }
}
          

Output

[3, 1, 2]
          

4. Accessing Elements Using Index (Slower than ArrayList)

import java.util.*;

class Demo {
    public static void main(String[] args) {
        LinkedList<String> list = new LinkedList<>(Arrays.asList("A", "B", "C"));
        System.out.println(list.get(1));
    }
}
          

Output

B
          

5. Adding Element at First Position

import java.util.*;

class Demo {
    public static void main(String[] args) {
        LinkedList<Integer> list = new LinkedList<>();
        list.add(10);
        list.addFirst(5);
        System.out.println(list);
    }
}
          

Output

[5, 10]
          

6. Adding Element at Last Position

import java.util.*;

class Demo {
    public static void main(String[] args) {
        LinkedList<Integer> list = new LinkedList<>();
        list.add(10);
        list.addLast(20);
        System.out.println(list);
    }
}
          

Output

[10, 20]
          

7. Removing First Element

import java.util.*;

class Demo {
    public static void main(String[] args) {
        LinkedList<String> list = new LinkedList<>(Arrays.asList("A", "B", "C"));
        list.removeFirst();
        System.out.println(list);
    }
}
          

Output

[B, C]
          

8. Removing Last Element

import java.util.*;

class Demo {
    public static void main(String[] args) {
        LinkedList<String> list = new LinkedList<>(Arrays.asList("A", "B", "C"));
        list.removeLast();
        System.out.println(list);
    }
}
          

Output

[A, B]
          

9. LinkedList as a Queue (FIFO)

import java.util.*;

class Demo {
    public static void main(String[] args) {
        LinkedList<Integer> queue = new LinkedList<>();
        queue.offer(10);
        queue.offer(20);
        System.out.println(queue.poll());
        System.out.println(queue);
    }
}
          

Output

10
[20]
          

10. LinkedList as a Stack (LIFO)

import java.util.*;

class Demo {
    public static void main(String[] args) {
        LinkedList<Integer> stack = new LinkedList<>();
        stack.push(10);
        stack.push(20);
        System.out.println(stack.pop());
        System.out.println(stack);
    }
}
          

Output

20
[10]
          

11. Iterating Using for-each Loop

import java.util.*;

class Demo {
    public static void main(String[] args) {
        LinkedList<String> list = new LinkedList<>(Arrays.asList("X", "Y", "Z"));
        for (String s : list) {
            System.out.println(s);
        }
    }
}
          

12. Iterating Using Iterator

import java.util.*;

class Demo {
    public static void main(String[] args) {
        LinkedList<Integer> list = new LinkedList<>(Arrays.asList(1, 2, 3));
        Iterator<Integer> it = list.iterator();
        while (it.hasNext()) {
            System.out.println(it.next());
        }
    }
}
          

13. Iterating Forward & Backward Using ListIterator

import java.util.*;

class Demo {
    public static void main(String[] args) {
        LinkedList<String> list = new LinkedList<>(Arrays.asList("A", "B", "C"));
        ListIterator<String> it = list.listIterator();

        while (it.hasNext()) {
            System.out.print(it.next() + " ");
        }
        while (it.hasPrevious()) {
            System.out.print(it.previous() + " ");
        }
    }
}
          

Output

A B C C B A
          

14. Removing Element While Iterating (Safe Way)

import java.util.*;

class Demo {
    public static void main(String[] args) {
        LinkedList<Integer> list = new LinkedList<>(Arrays.asList(1, 2, 3));
        Iterator<Integer> it = list.iterator();
        while (it.hasNext()) {
            if (it.next() == 2) {
                it.remove();
            }
        }
        System.out.println(list);
    }
}
          

Output

[1, 3]
          

15. LinkedList Size

import java.util.*;

class Demo {
    public static void main(String[] args) {
        LinkedList<String> list = new LinkedList<>(Arrays.asList("A", "B", "C"));
        System.out.println(list.size());
    }
}
          

Output

3
          

16. Checking Element Existence

import java.util.*;

class Demo {
    public static void main(String[] args) {
        LinkedList<String> list = new LinkedList<>(Arrays.asList("Java", "API"));
        System.out.println(list.contains("Java"));
    }
}
          

Output

true
          

17. Converting LinkedList to ArrayList

import java.util.*;

class Demo {
    public static void main(String[] args) {
        LinkedList<String> linkedList = new LinkedList<>(Arrays.asList("A", "B"));
        ArrayList<String> arrayList = new ArrayList<>(linkedList);
        System.out.println(arrayList);
    }
}
          

Output

[A, B]
          

18. LinkedList vs ArrayList (Insertion Performance)

import java.util.*;

class Demo {
    public static void main(String[] args) {
        LinkedList<Integer> list = new LinkedList<>();
        list.add(0, 100); // fast insertion
        System.out.println(list);
    }
}
          

Explanation

Insert/delete faster than ArrayList

Random access slower

19. LinkedList Is Not Thread-Safe

import java.util.*;

class Demo {
    public static void main(String[] args) {
        LinkedList<String> list = new LinkedList<>();
        list.add("Not Thread Safe");
        System.out.println(list);
    }
}
          

Explanation

Use Collections.synchronizedList() if needed

20. Interview Summary – LinkedList

import java.util.*;

class Demo {
    public static void main(String[] args) {
        LinkedList<String> list = new LinkedList<>();
        list.add("Doubly");
        list.add("Linked");
        list.add("List");
        System.out.println(list);
    }
}
          

Key Points

  • Doubly linked list
  • Faster insert/delete
  • Slower random access
  • Implements List and Deque
  • Allows duplicates & maintains order

Interview-Ready Answers

Short Answer

LinkedList is a doubly linked list implementation of the List interface.

Detailed Answer

In Java, LinkedList implements both List and Deque interfaces. It stores elements as nodes with previous and next references, allowing fast insertion and deletion but slower random access compared to ArrayList.

Key Takeaway

Use LinkedList when modification speed matters more than access speed. Choose wisely based on access pattern and performance needs.