00:00

Difference Between Array and ArrayList in Java

An array is a fixed-size, built-in language structure that stores elements of one type, including primitives, in consecutive memory. An ArrayList is a class from the Collections Framework that wraps an array and grows automatically, offering methods to add, remove, search and sort elements, but it stores only objects.

Both give fast access by index. The choice mostly depends on whether the size is fixed and whether you need primitives or the convenience of the List API.

1. Comparison Table

AspectArrayArrayList
SizeFixed when createdDynamic; grows by about 50% when full
Element typesPrimitives and objectsObjects only (primitives are autoboxed)
Length / sizearr.length (field)list.size() (method)
Access syntaxarr[i]list.get(i), list.set(i, x)
Adding / removingNot possible; create a new arrayadd, remove, insert at any position
Type safetyChecked at run time (ArrayStoreException)Checked at compile time with generics
DimensionsMultidimensional supported directlyOne-dimensional (nest lists for more)
PerformanceSlightly faster, less memory, no boxingSmall overhead; boxing for primitives
Utility methodsVia java.util.ArraysBuilt in, plus Collections and streams
Part ofJava languageCollections Framework (java.util)

2. Side-by-Side Example

ArrayVsArrayList.java
import java.util.*;

public class ArrayVsArrayList {
    public static void main(String[] args) {
        // Array: fixed size, can hold primitives, length field
        int[] scores = new int[3];
        scores[0] = 90; scores[1] = 85; scores[2] = 77;
        System.out.println("array       : " + Arrays.toString(scores) + ", length = " + scores.length);
        try {
            scores[3] = 60;                                  // no room to grow
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("array grow  : " + e.getClass().getSimpleName());
        }

        // ArrayList: resizable, objects only (autoboxing), size() method, rich API
        List<Integer> list = new ArrayList<>(List.of(90, 85, 77));
        list.add(60);                                        // grows automatically
        list.remove(Integer.valueOf(85));                    // remove by value
        list.add(1, 99);                                     // insert in the middle
        System.out.println("ArrayList   : " + list + ", size = " + list.size());
        System.out.println("contains 77 : " + list.contains(77) + ", indexOf 60: " + list.indexOf(60));
        Collections.sort(list);
        System.out.println("sorted      : " + list);
    }
}
Output
array       : [90, 85, 77], length = 3
array grow  : ArrayIndexOutOfBoundsException
ArrayList   : [90, 99, 77, 60], size = 4
contains 77 : true, indexOf 60: 3
sorted      : [60, 77, 90, 99]

The array cannot hold a fourth score, while the list grows, inserts in the middle and removes by value. Note list.remove(Integer.valueOf(85)): calling remove(85) would remove the element at index 85.

3. Converting Between Them

ConvertBetween.java
import java.util.*;

public class ConvertBetween {
    public static void main(String[] args) {
        String[] arr = {"java", "spring", "kafka"};

        List<String> list = new ArrayList<>(Arrays.asList(arr));   // array -> ArrayList
        list.add("docker");
        System.out.println("to list  : " + list);

        String[] back = list.toArray(new String[0]);                // ArrayList -> array
        System.out.println("to array : " + Arrays.toString(back) + " (" + back.length + ")");

        int[] nums = {3, 1, 2};
        List<Integer> boxed = new ArrayList<>(Arrays.stream(nums).boxed().toList());   // int[] -> List<Integer>
        int[] unboxed = boxed.stream().mapToInt(Integer::intValue).toArray();          // List<Integer> -> int[]
        System.out.println("boxed    : " + boxed + ", unboxed: " + Arrays.toString(unboxed));

        int[][] grid = new int[2][3];                               // multidimensional arrays are natural
        grid[1][2] = 5;
        System.out.println("2D array : " + Arrays.deepToString(grid));
    }
}
Output
to list  : [java, spring, kafka, docker]
to array : [java, spring, kafka, docker] (4)
boxed    : [3, 1, 2], unboxed: [3, 1, 2]
2D array : [[0, 0, 0], [0, 0, 5]]
  • Arrays.asList returns a fixed-size view; wrap it in new ArrayList<>(...) to get a growable list.
  • list.toArray(new String[0]) returns a correctly typed array.
  • For primitives, use streams: boxed() and mapToInt.

4. Performance and Memory

  • Both offer O(1) access by index; ArrayList.get is essentially an array access plus a bounds check.
  • An int[] stores 4 bytes per element; an ArrayList<Integer> stores a reference plus an Integer object for each value, using several times more memory.
  • Appending to an ArrayList is amortised O(1), but each growth step copies the array. Pre-size it with new ArrayList<>(capacity) when you know the count.
  • Inserting or removing in the middle of an ArrayList is O(n), because elements shift.

5. When to Use Which

Use an array when…Use an ArrayList when…
The size is fixed and knownThe number of elements changes
You store many primitives and performance or memory mattersYou need add, remove, contains, sort and stream conveniences
You need multidimensional data (matrices, grids)You pass data to APIs that expect List or Collection
Working with low-level APIs (bytes, I/O buffers)Writing typical business code

6. Summary

  • Arrays have a fixed size and can hold primitives; ArrayList resizes automatically and holds objects.
  • Use length for arrays and size() for lists.
  • Arrays are leaner and faster for primitives; ArrayList is more flexible and type-safe with generics.
  • Convert with Arrays.asList, toArray or streams.

Related Tutorials