ArrayList

About

ArrayList is a part of the Java Collections Framework and resides in the java.util package. It is a resizable array implementation of the List interface and provides dynamic array capabilities. Unlike standard arrays, ArrayList can grow and shrink dynamically, making it more flexible when dealing with an unknown number of elements.

Features of ArrayList

  1. Dynamic Resizing: Automatically resizes as elements are added or removed.

  2. Random Access: Allows retrieving elements in constant time, O(1), using indices.

  3. Duplicates Allowed: Allows duplicate elements, unlike Set.

  4. Maintains Insertion Order: Elements are stored in the order they are inserted.

  5. Generic Support: Enables type safety, preventing runtime ClassCastException.

    ArrayList<String> names = new ArrayList<>();
  6. Custom Capacity Management: Initial capacity can be set to avoid frequent resizing.

    ArrayList<Integer> numbers = new ArrayList<>(100);
  7. Serialization Support: Implements Serializable, making it suitable for object serialization.

  8. Iterator and ListIterator Support: Traversing the list in both forward and backward directions.

  9. Fail-Fast Behavior: Throws ConcurrentModificationException if the list is structurally modified while iterating.

Key Methods

  • add(E e): Adds an element.

  • get(int index): Retrieves an element by index.

  • set(int index, E element): Replaces the element at a specified position.

  • remove(int index) / remove(Object o): Removes an element.

  • size(): Returns the number of elements.

  • isEmpty(): Checks if the list is empty.

  • contains(Object o): Checks if the list contains a specified element.

  • clear(): Removes all elements.

  • addAll(Collection<? extends E> c): Adds all elements of a collection.

  • retainAll(Collection<?> c): Retains only elements present in the specified collection.

  • subList(int fromIndex, int toIndex): Returns a portion of the list.

  • toArray(): Converts the list into an array.

Big(O) for Operations on ArrayList

The performance of ArrayList operations depends on the dynamic resizing of the internal array and how elements are accessed or modified. Below is the time complexity for various operations:

Operation

Big(O) Time Complexity

Details

Access by Index

O(1)

Direct indexing makes retrieval constant time.

Add (at end)

O(1) Amortized

Appending is constant unless resizing occurs (then O(n) for resizing).

Add (at specific index)

O(n)

Shifts elements after the index to the right.

Remove (by index)

O(n)

Shifts elements after the removed index to the left.

Remove (by value)

O(n)

Searches for the value first (O(n)) and then removes it.

Search (by value)

O(n)

Iterates through the array to find the value.

Contains

O(n)

Iterates through the array to check if the value exists.

Iteration (using for-loop)

O(n)

Iterates through each element once.

Dynamic Resizing (growth)

O(n) Rarely occurs

Copies all elements to a new larger array when resizing.

Examples

Basic Operation

Generic ArrayLists

circle-info
  • Type Safety:

    • The ArrayList is declared with the generic type <Integer>.

    • This ensures that only Integer objects can be added to intList, avoiding runtime ClassCastException.

    • Generics enforce compile-time type checking.

  • Stream API Compatibility:

    • The intList.stream() method returns a Stream<Integer> because the list is generic with Integer type.

    • The stream operation .mapToInt(Integer::intValue) converts the Stream<Integer> into an IntStream for summation.

    • This operation is efficient because it avoids boxing/unboxing operations during summation.

  • Eliminating Casting:

    • Without generics, we would need to cast objects manually when retrieving elements, which is error-prone:

Custom Sorting with Comparators

Using Streams

Last updated