List — ArrayList & LinkedList
লিস্ট — Java-র সবচেয়ে বেশি ব্যবহৃত collection; কবে কোনটি ব্যবহার করবেন
1. The List Interface
List<T> is Java's ordered, index-accessible, duplicate-allowing collection contract. Every
real implementation — ArrayList, LinkedList, CopyOnWriteArrayList,
Vector — implements the same interface. That is the power of the Collections Framework:
you code against List, and swap the implementation later if the performance profile changes.
List<T> হলো Java-র ordered, index-ভিত্তিক, duplicate-allowed collection-এর contract। ArrayList, LinkedList, Vector, CopyOnWriteArrayList — সবাই একই interface implement করে। সাধারণভাবে List-এর বিরুদ্ধে code লিখুন, দরকারে implementation পরে বদলে দিন।
ArrayList 99% of the time.
LinkedList exists mainly to serve as a Deque.
৯৯% ক্ষেত্রে
ArrayList-ই সঠিক। LinkedList আজকাল প্রধানত Deque implementation হিসেবে ব্যবহৃত।
2. ArrayList — The Default Choice
ArrayList wraps a growable array. Random access get(i) is O(1),
add at the end is amortized O(1), and iteration is cache-friendly. The
only weakness is insertion/removal in the middle — those are O(n) because elements must shift.
ArrayList-এর ভেতরে growable array। get(i) = O(1), শেষে add = amortized O(1), iteration cache-friendly। মাঝখানে insert/remove O(n) — কারণ element গুলো shift করতে হয়।
import java.util.*;
class Main {
public static void main(String[] args) {
List<String> cities = new ArrayList<>();
cities.add("Dhaka");
cities.add("Chattogram");
cities.add("Sylhet");
cities.add(1, "Khulna"); // insert at index 1
System.out.println(cities);
System.out.println("size = " + cities.size());
System.out.println("get(2) = " + cities.get(2));
cities.remove("Sylhet");
System.out.println("after remove: " + cities);
}
}
3. LinkedList — Doubly-Linked Nodes
LinkedList is a doubly-linked list of node objects. addFirst/addLast
and removeFirst/removeLast are all O(1), but get(i)
requires walking from one end — O(n). Each node also costs extra memory for two pointers.
LinkedList হলো doubly-linked list। দুই প্রান্তে add/remove = O(1), কিন্তু get(i) = O(n) কারণ একদিক থেকে হাঁটতে হয়। প্রতিটি node-এর দুটি pointer-এর জন্য বাড়তি memory খরচ।
List interface, ভিতরে ভিন্ন memory layout।
4. Iterators & ConcurrentModificationException
Modifying a list while iterating with a for-each loop throws ConcurrentModificationException.
The safe way to remove during iteration is to use the Iterator explicitly and call
iterator.remove(), or to use the List.removeIf(predicate) method.
ConcurrentModificationException (CME) হয়। নিরাপদ উপায় — Iterator-এর remove() কল করা অথবা list.removeIf(predicate) ব্যবহার।
import java.util.*;
class Main {
public static void main(String[] args) {
List<Integer> nums = new ArrayList<>(List.of(1, 2, 3, 4, 5, 6));
// Option A: Iterator.remove()
Iterator<Integer> it = nums.iterator();
while (it.hasNext()) {
if (it.next() % 2 == 0) it.remove();
}
System.out.println("after iterator.remove: " + nums);
// Option B: removeIf (Java 8+)
List<Integer> xs = new ArrayList<>(List.of(1, 2, 3, 4, 5, 6));
xs.removeIf(n -> n % 2 == 0);
System.out.println("after removeIf: " + xs);
}
}
5. List.of(...) — Immutable Lists
Since Java 9, List.of(a, b, c) creates a compact, immutable list. Attempting to add,
remove, or set throws UnsupportedOperationException. Use it for
constants and defensive copies.
List.of(...) immutable list দেয়। add/remove/set করলে UnsupportedOperationException হবে। Constant বা defensive copy-র জন্য উপযুক্ত।
import java.util.*;
class Main {
public static void main(String[] args) {
List<String> fixed = List.of("red", "green", "blue");
System.out.println(fixed);
try {
fixed.add("yellow");
} catch (UnsupportedOperationException ex) {
System.out.println("Cannot mutate: " + ex.getClass().getSimpleName());
}
}
}
6. Complexity & Vocabulary
| Operation | ArrayList | LinkedList | বাংলায় |
|---|---|---|---|
get(i) | O(1) | O(n) | ArrayList-ই দ্রুত। |
add(e) at end | Amortized O(1) | O(1) | উভয়েই দ্রুত। |
add(0, e) at front | O(n) | O(1) | LinkedList জেতে। |
remove(i) middle | O(n) shift | O(n) walk | দুটিই ধীর। |
| Memory overhead | Low | High (2 pointers/node) | ArrayList হালকা। |
| Cache friendliness | Excellent | Poor | ArrayList স্পষ্ট এগিয়ে। |
7. Practice Problems
-
Create an
ArrayList<String>of five colors and print them in reverse order.পাঁচটি রং-এর একটিArrayList<String>বানিয়ে উল্টো ক্রমে প্রিন্ট করুন।✨ Show Answer
Main.javaimport java.util.*; class Main { public static void main(String[] args) { List<String> colors = new ArrayList<>(List.of("red", "green", "blue", "yellow", "pink")); Collections.reverse(colors); System.out.println(colors); } } -
Remove all odd numbers from a list of 1..10 using
removeIf.1..10 list থেকে সব বিজোড় সংখ্যাremoveIfদিয়ে মুছুন।✨ Show Answer
Main.javaimport java.util.*; class Main { public static void main(String[] args) { List<Integer> xs = new ArrayList<>(); for (int i = 1; i <= 10; i++) xs.add(i); xs.removeIf(n -> n % 2 != 0); System.out.println(xs); } } -
Explain the amortized
O(1)cost ofArrayList.addat the end.ArrayList.add-এ amortized O(1) মানে কী — ব্যাখ্যা করুন।✨ Show Answer
Answer: The backing array grows by roughly 1.5× when full. Most
addcalls are just one slot assignment —O(1). Occasionally the array doubles/grows, which costsO(n). Spread acrossnadds, total work isO(n), so the average per operation isO(1)— that is what "amortized" means.ভিতরের array ~1.5× করে বাড়ে। বেশির ভাগ
addশুধু একটি index-এ value বসানো — O(1)। কখনো কখনো array-কে resize করতে হয় (O(n)), কিন্তু n-সংখ্যক add-এ মোট O(n), তাই গড়ে প্রতিটি = O(1) — এটাই amortized। -
Show a safe way to remove all empty strings from a
List<String>while iterating.iterating অবস্থায়List<String>থেকে সব empty string নিরাপদে মুছুন।✨ Show Answer
Main.javaimport java.util.*; class Main { public static void main(String[] args) { List<String> xs = new ArrayList<>(List.of("a", "", "b", "", "c")); Iterator<String> it = xs.iterator(); while (it.hasNext()) { if (it.next().isEmpty()) it.remove(); } System.out.println(xs); } } -
Give one scenario where
LinkedListis genuinely the better choice.কোন এক পরিস্থিতিতেLinkedListসত্যিই ভালো — ব্যাখ্যা করুন।✨ Show Answer
Answer: Use
LinkedListas aDequewhen you frequently add/remove from both ends — for example, a fixed-size recent-history buffer where each event is pushed at the front and old events drop off the back. Even here, most modern code usesArrayDeque, which beatsLinkedListfor cache friendliness and speed. So in real practice,LinkedList's niche is small.দুই প্রান্তে বারবার add/remove হলে (যেমন recent-history buffer)। তবে সেক্ষেত্রেও আধুনিক code সাধারণত
ArrayDequeবেছে নেয় — cache-friendly এবং দ্রুত। তাইLinkedList-এর প্রকৃত ব্যবহারিক ক্ষেত্র খুব সীমিত।
Summary — Module 23
List<T> is Java's ordered, indexable, duplicate-allowed collection.
ArrayList is the default — fast random access and tight memory.
LinkedList wins only when you need cheap add/remove at both ends.
Mutate safely with Iterator.remove() or removeIf(...). Use
List.of(...) for immutable constants.
List<T> Java-র ordered, index-ভিত্তিক, duplicate-allowed collection। ArrayList default — দ্রুত random access এবং কম memory। LinkedList শুধু দুই প্রান্তে add/remove-এ ভালো। Iterator.remove() বা removeIf() দিয়ে safely modify করুন। Constant-এর জন্য List.of(...)।