Time Complexity of Collection Operations

Naveen AnamaneniUpdated · 5 min read

Time complexity describes how the time an operation takes grows as a collection gets bigger. It is written in Big O notation: O(1) means the time stays the same however many elements there are, O(log n) means it grows very slowly, and O(n) means it grows in step with the number of elements. Knowing these costs is how you choose the right collection, and it is asked in nearly every Java interview. In this lesson, you will find the cost of the main operations for each collection, and see why each is what it is.

Big O in Plain Words

NotationNameWith 1,000,000 elements, roughlyExample
O(1)Constant1 stepArrayList.get(i), HashMap.get(k)
O(log n)Logarithmic20 stepsTreeMap.get(k)
O(n)Linear1,000,000 stepsArrayList.contains(x)
O(n log n)Linearithmic20,000,000 stepsCollections.sort(list)

"Amortized O(1)" means usually O(1), with an occasional slow step (like resizing) whose cost, spread over many operations, is still constant on average.

Lists

OperationArrayListLinkedList
get(i) / set(i, e)O(1)O(n)
add(e) at the endO(1) amortizedO(1)
add(0, e) / remove(0)O(n)O(1)
add(i, e) / remove(i) in the middleO(n)O(n)
contains(e) / indexOf(e)O(n)O(n)
Iterating over all elementsO(n)O(n)

Sets

OperationHashSet / LinkedHashSetTreeSetEnumSet
addO(1) averageO(log n)O(1)
removeO(1) averageO(log n)O(1)
containsO(1) averageO(log n)O(1)
first / floor / ceilingNot availableO(log n)Not available

Maps

OperationHashMap / LinkedHashMapTreeMapEnumMap
putO(1) averageO(log n)O(1)
getO(1) averageO(log n)O(1)
removeO(1) averageO(log n)O(1)
containsKeyO(1) averageO(log n)O(1)
containsValueO(n)O(n)O(n)
firstKey / floorKeyNot availableO(log n)Not available

HashMap is O(log n) in the worst case, when many keys collide in one bucket that has turned into a tree.

Queues and Deques

OperationArrayDequePriorityQueue
offer / addO(1) amortized (either end)O(log n)
poll / remove the headO(1)O(log n)
peekO(1)O(1)
contains / remove(Object)O(n)O(n)

Example: O(1) vs O(n) in Practice

Let's see an example that searches for values in a list and a set of the same size. Times vary between computers, so the output is a sample.

ContainsCost.java▶ Try it
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
 
public class ContainsCost {
    public static void main(String[] args) {
        int n = 100_000;
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            list.add(i);
        }
        Set<Integer> set = new HashSet<>(list);
 
        long start = System.nanoTime();
        int found = 0;
        for (int i = 0; i < 10_000; i++) {
            if (list.contains(n - 1 - i)) found++;
        }
        long listMs = (System.nanoTime() - start) / 1_000_000;
 
        start = System.nanoTime();
        for (int i = 0; i < 10_000; i++) {
            if (set.contains(n - 1 - i)) found++;
        }
        long setMs = (System.nanoTime() - start) / 1_000_000;
 
        System.out.println("found " + found);
        System.out.println("ArrayList.contains x 10,000: " + listMs + " ms");
        System.out.println("HashSet.contains   x 10,000: " + setMs + " ms");
    }
}
Output
found 20000
ArrayList.contains x 10,000: 257 ms
HashSet.contains   x 10,000: 0 ms

Explanation: Each ArrayList.contains scans the list from the start, about 100,000 comparisons for values near the end. HashSet.contains jumps straight to one bucket. With 10,000 searches, the difference is hundreds of times.

Common Mistakes

Calling list.contains inside a loop over another big list. That is O(n x m); use a HashSet for lookups.

Using LinkedList.get(i) in a loop. Each call is O(n), making the loop O(n squared).

Forgetting that containsValue on a map is O(n). Only key lookups are fast.

Interview Corner

What is the time complexity of HashMap get and put?

O(1) on average, because the key's hash leads straight to one bucket that usually holds zero or one entry. In the worst case, when many keys collide in one bucket, it is O(log n) since Java 8, because large buckets are converted to red-black trees (it was O(n) before Java 8).

Why is TreeMap O(log n)?

TreeMap stores its entries in a red-black tree, a balanced binary search tree whose height stays proportional to log n. Every get, put and remove walks from the root down one path of the tree, so it takes O(log n) steps.

Practice

  1. Easy: For each of these tasks, name the collection with the best cost: checking whether a username is taken; getting the 500th element; always serving the smallest job first.
  2. Harder: Find the common elements of two lists of 100,000 numbers, first with nested contains calls, then with a HashSet. Time both and explain the difference using Big O.

Quick check: Time complexity

4 questions
1What is the cost of ArrayList.get(i)?
2What is the cost of TreeSet.contains?
3Which is O(n) on a HashMap?
4What is the cost of PriorityQueue.poll()?

Key Takeaways

Was this tutorial helpful?

Lesson 300 of 482