Big-O Notation — The Complexity Classes Every Java Developer Must Know
Fast recall
Quick revision
Core answer
n grows to infinity. It expresses how the cost scales with input, not the absolute time. We drop constants and lower-order terms — O(3n + 5) becomes O(n), O(n² + n) becomes O(n²) — because they don't matter as n gets large. The six complexity classes you need to know for interviews: O(1) constant — hash map lookup (HashMap.get); O(log n) logarithmic — binary search, TreeMap.get, balanced BST operations; O(n) linear — list traversal, ArrayList.contains, summing an array; O(n log n) linearithmic — efficient sorts (merge sort, Arrays.sort for objects, Collections.sort); O(n²) quadratic — nested loops over the same input (naive bubble sort, pairwise comparison); O(2^n) exponential — naive recursive Fibonacci, subset enumeration, brute-force TSP. Two related notations: Ω (big-Omega) for lower bound (“at least this slow”), Θ (big-Theta) for tight bound (both upper and lower) — but in practice, interviewers say “O” and usually mean Θ. Best / average / worst case matter: HashMap.get is O(1) average but O(n) worst case (hash collisions chain to a list, or to a tree for Java 8+). Big-O tells you how it scales; actual wall-clock time depends on constant factors, cache locality, and branch prediction — sometimes an O(n²) algorithm beats O(n log n) for small n (e.g., insertion sort on tiny arrays). The interview win: know the six classes, map each Java collection operation to one, and distinguish average vs worst case for HashMap/HashSet/TreeMap.Whether the candidate can name and rank the common complexity classes, give Java examples of each, distinguish O from Ω/Θ, and understand best/average/worst case
Confusing O(log n) with O(n log n). Saying HashMap.get() is always O(1) (it's O(1) *average*, O(n) worst case). Not dropping constants (calling it O(2n) instead of O(n))
Mention amortized analysis, Java 8 HashMap's treeification at 8 entries per bucket (changing worst case to O(log n)), constant-factor reality (cache locality, branch prediction), and when O(n²) beats O(n log n) for small n
Interview-ready guide
Interview answer
Big-O notation describes the asymptotic upper bound on how an algorithm's running time (or memory) scales with input size. We drop constants and lower-order terms because they don't matter as n gets large.
The six classes you need to know
O(1) — constant
- Independent of input size
- HashMap.get, HashSet.contains, array index, ArrayDeque.offer
- 1 step whether n is 10 or 10 million
O(log n) — logarithmic
- Each step halves the remaining work
- Binary search, TreeMap.get, PriorityQueue.poll
- 20 steps for n=1M
O(n) — linear
- Work proportional to input size
- ArrayList.contains, summing an array, list traversal
O(n log n) — linearithmic
- Collections.sort, Arrays.sort for objects, merge sort, Timsort
- Best achievable for comparison-based sorting
O(n²) — quadratic
- Nested loops over same input
- Bubble sort, naive pairwise comparison
- Becomes painful at n=1M (10^12 ops)
O(2^n) — exponential
- Naive recursive Fibonacci
- Subset enumeration
- Unusable beyond n≈30
Related notations
- O (big-O) — upper bound
- Ω (big-Omega) — lower bound
- Θ (big-Theta) — tight bound (both)
- Interview 'O' usually means Θ in practice
Best / average / worst case
- HashMap.get — O(1) average, O(log n) worst case since Java 8 (was O(n) prior due to linked list chains)
- QuickSort — O(n log n) average, O(n²) pathological
- Binary search — O(1) best, O(log n) average/worst
- TreeMap — always O(log n), no degenerate case
Amortized cost
- ArrayList.add is O(1) worst-case single op but O(n) occasional resize; amortized O(1)
- HashMap.put same story
- Amortization spreads the occasional O(n) across many O(1) ops
Computing Big-O from code
- Walk the code mentally, count operations as function of n
- Single loop: O(n)
- Nested loops same n: O(n²)
- Nested loops different vars: O(a·b)
- Loop with halving step: O(log n)
- Loop with inner binary search: O(n log n)
- Recursion that branches into 2: O(2^n)
- Divide and combine (merge sort): O(n log n) via master theorem
Common traps
1. O(n) operation inside O(n) loop → O(n²)
for (x : list) if (list.contains(y)) {...}— contains is O(n), total O(n²)- Fix: use HashSet — contains becomes O(1), total O(n)
2. Saying HashMap.get() is O(1) always
- It's O(1) average
- Worst case O(log n) since Java 8 (treeification at 8 entries per bucket)
- Worst case O(n) pre-Java 8
3. Not dropping constants
- O(3n) is O(n)
- O(500) is O(1)
- O(n + log n) is O(n)
When Big-O doesn't match real performance
- Constants matter: O(n) with low constant can beat O(log n) for small n
- Cache locality: ArrayList traversal beats LinkedList traversal (same Big-O)
- Branch prediction
- Memory allocation cost
- JIT optimization of hot paths
- For n < 50, insertion sort (O(n²)) beats merge sort (O(n log n)) — Timsort exploits this
Takeaway
- Big-O is necessary but not sufficient
- For algorithm choice: use Big-O
- For hot-path performance: benchmark
- For Java collections: know average AND worst case
Recommendation: For Java interviews, memorize the six complexity classes and map each Java collection operation to one. Know HashMap is O(1) average, O(log n) worst case (Java 8 treeification). Know ArrayList.add is amortized O(1) — resize is occasional. Know Collections.sort is O(n log n) — Timsort is stable and adaptive. Watch for the classic trap: O(n) operation inside O(n) loop (e.g., list.contains in a loop over list) — convert to HashMap/HashSet for O(n) total. Remember Big-O measures growth, not speed — constants and cache locality matter in practice, but for choosing between data structures, Big-O is your primary guide. When asked 'what's the complexity?' always specify best/average/worst for hash-based structures; give amortized for resize-based structures. Never say 'HashMap is always O(1)' — say 'O(1) average, O(log n) worst case since Java 8.' This demonstrates both depth and precision.
Big-O Notation — The Complexity Classes Every Java Developer Must Know
Direct Answer
Big-O notation describes the asymptotic upper bound on the growth rate of an algorithm's running time (or memory) as input size n grows to infinity. It expresses how the cost scales with input, not the absolute time. We drop constants and lower-order terms — O(3n + 5) becomes O(n), O(n² + n) becomes O(n²) — because they don't matter as n gets large. The six complexity classes you need to know for interviews: O(1) constant — hash map lookup (HashMap.get); O(log n) logarithmic — binary search, TreeMap.get, balanced BST operations; O(n) linear — list traversal, ArrayList.contains, summing an array; O(n log n) linearithmic — efficient sorts (merge sort, Arrays.sort for objects, Collections.sort); O(n²) quadratic — nested loops over the same input (naive bubble sort, pairwise comparison); O(2^n) exponential — naive recursive Fibonacci, subset enumeration, brute-force TSP. Two related notations: Ω (big-Omega) for lower bound (“at least this slow”), Θ (big-Theta) for tight bound (both upper and lower) — but in practice, interviewers say “O” and usually mean Θ. Best / average / worst case matter: HashMap.get is O(1) average but O(n) worst case (hash collisions chain to a list, or to a tree for Java 8+). Big-O tells you how it scales; actual wall-clock time depends on constant factors, cache locality, and branch prediction — sometimes an O(n²) algorithm beats O(n log n) for small n (e.g., insertion sort on tiny arrays). The interview win: know the six classes, map each Java collection operation to one, and distinguish average vs worst case for HashMap/HashSet/TreeMap.
Common Mistakes & Pitfalls
Confusing O(log n) with O(n log n). Saying HashMap.get() is always O(1) (it's O(1) average, O(n) worst case). Not dropping constants (calling it O(2n) instead of O(n))
Check your understanding
Answer these without looking back at the article.
- Why is HashMap.get() O(log n) worst case since Java 8 instead of O(n)?
- What's the difference between O, Ω, and Θ?
- When does an O(n²) algorithm outperform O(n log n) in practice?
- Why is ArrayList.add() amortized O(1) when a single add can be O(n)?
- How do you compute the time complexity of a recursive function?
Related interview prep categories
1Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.