Deep Dive into ArrayList and LinkedList Source Code Implementation

一 Arraylist

1、Three Implemented Interfaces

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable

RandomAccess Interface: The ArrayList class implements the RandomAccess interface, which indicates that it supports efficient random access—accessing elements directly through their index.

Cloneable Interface: ArrayList implements the Cloneable interface, enabling object cloning through the clone() method.

Serializable Interface: The ArrayList class implements the Serializable interface, allowing it to be serialized for network transmission or file storage.

In Java, when a non-abstract class implements an interface, it must provide implementations for all methods defined in that interface.

2、Understanding the Three Array Objects

EMPTY_ELEMENTDATA: This is a globally shared empty array instance used to represent completely empty ArrayList objects. EMPTY_ELEMENTDATA is initialized as an empty array {}. Whenever the code requires an empty array instance, it can directly reference EMPTY_ELEMENTDATA instead of creating new empty array objects repeatedly.

DEFAULTCAPACITY_EMPTY_ELEMENTDATA: This is another globally shared empty array instance used to represent empty ArrayList objects with default capacity (typically 10 elements) at initialization.

elementData: This is the actual array that stores ArrayList elements. Its contents change dynamically based on ArrayList operations. In this declarasion, the elementData array is marked as transient, meaning its contents are not preserved when serializing objects containing this field. This is an optimization since elementData may contain unused space, and serializing unused capacity would negatively impact performance.

3、Constructor from Collection

public ArrayList(Collection<? extends E> c) {
    Object[] arrayData = c.toArray();
    if ((elementCount = arrayData.length) != 0) {
        if (c.getClass() == ArrayList.class) {
            this.elementData = arrayData;
        } else {
            this.elementData = Arrays.copyOf(arrayData, elementCount, Object[].class);
        }
    } else {
        this.elementData = EMPTY_ELEMENTDATA;
    }
}

toArray Method: Converts a collection to an array.

Special Handling: If the input parameter is an ArrayList instance, all elements from that parameter are assigned directly to the elementData array. Otherwise, Arrays.copyOf() is used to create a copy of arrayData and convert it to Object[] type before assignment to elementData. This ensures elementData always remains an Object[] array type.

4、Understanding Arrays.copyOf

int[] sourceArray = {10, 20, 30, 40, 50};
int[] targetArray = Arrays.copyOf(sourceArray, 3);
// targetArray now contains {10, 20, 30}

This utility functon creates a new array and copies elements of the specified length from the source array in to the new array.

5、Clone Operation is Shallow

When calling clone() on an ArrayList, only the ArrayList object itself is duplicated. The internal elementData array is shared between the original and cloned instances. Modifications to elements through one reference will be visible through the other. This behavior is known as a shallow copy.

6、Wildcards in Generics

Java generics support wildcards to increase flexibility when working with type parameters. When using generic classes, you can specify a concrete type like List or use the wildcard ? to represent an unknown type like List.

Wildcards represent a set of types rather than a specific type. List declares that the element types are unknown but any type is acceptable. However, List is not equivalent to List.

List explicitly allows Object and its subclasses, meaning all elements can be referenced through Object type. With List, the element type is uncertain—it might contain Strings, Integers, or other types. Attempting to add an Integer to a List containing Strings would be incorrect.

Due to type uncertainty, you cannot create a new ArrayList through new ArrayList(). The compiler cannot determine the specific type. However, elements in List can always be referenced through Object since they must be objects.

Consider this example:

public void processWildcard(List<?> items) {
    items.add(42);  // Compilation error
}

Operations on generic types with wildcards produce compilation errors because the wildcard represents an unknown type.

? Wildcards Serve as Consumers Only: Since elements in List can only be referenced through Object, this is sometimes inconvenient. In such cases, bounded wildcards can restrict the unknown type's range. List

Tags: java ArrayList linkedlist Collections generics

Posted on Fri, 15 May 2026 18:42:21 +0000 by dleone