The Ultimate Guide to Java's ArrayList: Beyond the Basics


πŸ“– Table of Contents

  1. What is an ArrayList?
  2. Key Features
  3. Internal Implementation
  4. Basic Operations
  5. Common Use Cases
  6. Performance and Time Complexity
  7. ArrayList vs LinkedList
  8. Sample Code Examples
  9. Trick & Interview Questions
  10. References

What is an ArrayList?

An ArrayList is a part of Java’s Collections Framework. It implements the List interface and stores elements in a resizable array. Unlike regular arrays, which have a fixed size, an ArrayList can dynamically grow or shrink as elements are added or removed.

List<String> names = new ArrayList<>();

Key Features

  • βœ… Dynamic Sizing – Grows or shrinks as needed.
  • βœ… Index-based Access – Constant-time retrieval (get(index)).
  • ❌ Not Thread-safe – Must use external synchronization in multi-threaded environments.
  • βœ… Allows Nulls & Duplicates – Supports duplicate elements and null values.
  • βœ… Preserves Insertion Order – Elements maintain the order they were added.

Internal Implementation

How It Works:

  1. Initialization: : List is initialized with empty shared array

    /**
    * Shared empty array instance used for empty instances.
    */
    private static final Object[] EMPTY_ELEMENTDATA = {};
    /**
    * Shared empty array instance used for default sized empty instances. We
    * distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
    * first element is added.
    */
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
  2. Adding Elements: When you add an element to an ArrayList

    • If the backing array is full, the ArrayList creates a new array with a larger capacity. Typically, the new capacity is about 1.5 times the current capacity.
    • It then copies elements from the old array to the new one and adds the new element.
  3. Accessing Elements: Accessing elements by index is straightforward and fast, as it directly references the array index.

  4. Removing Elements: Removing elements involves shifting any subsequent elements to the left to fill the gap, which can make removal slower compared to addition.

Resizing logic (simplified):

newCapacity = oldCapacity + (oldCapacity >> 1); // ~1.5x
  • Remove operation shifts elements left to fill the gap.
  • TrimToSize() can be used to minimize memory.

Basic Operations

OperationMethodTime Complexity
Add Elementadd(E e)Amortized O(1)
Get Elementget(int index)O(1)
Remove Elementremove(int index)O(n)
Search Elementcontains(Object o)O(n)
Iteratefor, iterator()O(n)
Resize (internal)Auto-handledO(n)

Common Use Cases

  • Frequent read or access by index
  • Lists where insertion order matters
  • When fast iteration is preferred over fast inserts/removals
  • UI elements, log history, batch data loading

Performance and Time Complexity

OperationArrayListLinkedList
get(index)O(1)O(n)
add()O(1)*O(1)
remove(index)O(n)O(n)
insert at middleO(n)O(n)
memory overheadLowHigh
  • * Amortized due to resizing

Use ArrayList when: - Access by index is frequent - You don’t need thread safety - Memory overhead needs to be minimal


ArrayList vs LinkedList

FeatureArrayListLinkedList
Backed ByDynamic ArrayDoubly Linked List
Access TimeFast (O(1))Slow (O(n))
Insert/Remove at EndsSlower (due to shifts)Fast (O(1))
Memory EfficiencyMore compactMore memory per node
Best UseAccess-heavy tasksFrequent insert/delete operations

πŸ”— See official comparison


Sample Code Examples

1. Creating and Adding Elements

List<String> list = new ArrayList<>();
list.add("Apple");
list.add("Banana");

2. Iterating

for (String item : list) {
System.out.println(item);
}

3. Access & Modify

String first = list.get(0);
list.set(1, "Orange");

4. Removing Elements

list.remove("Apple");
list.remove(0);

5. Sorting

Collections.sort(list);

Trick & Interview Questions

βœ… Concept Check

  • πŸ”Έ What happens if the backing array is full?
  • πŸ”Έ Why is ArrayList not thread-safe? How to make it so?
  • πŸ”Έ What’s the time complexity of remove(index)?

⚠️ Trick Questions

  • Q: Can an ArrayList hold primitive types? A: No. It holds objects. Java autoboxes primitives (e.g., int to Integer).

  • Q: Does setting initial capacity improve performance? A: Yes, it reduces internal resizing if you know the approximate size ahead of time.

  • Q: Will remove(Object) remove all matching items? A: No. Only the first occurrence is removed.

  • Q: How do you create a thread-safe ArrayList? A: Use Collections.synchronizedList(new ArrayList<>()) or CopyOnWriteArrayList.

  • Q: What’s the difference between size() and capacity()? A: size() is the number of elements; capacity() is the current array length (not directly accessible but inferred via reflection or subclassing).


References