Back to Arrays
Q4Question 4 of 4

What are the key differences between an array and an ArrayList?

Key Concepts
  • Array: fixed size, can hold primitives and objects, type-safe at runtime (ArrayStoreException)
  • ArrayList: dynamic size, holds only objects (autoboxes primitives), type-safe at compile time (generics)
  • Array: faster for random access and primitives (no autoboxing overhead)
  • ArrayList: easier to use – add, remove, contains, sort built in
  • Array: length field; ArrayList: size() method
  • Use arrays for fixed-size primitives; use ArrayList for everything else

Definition

Arrays are fixed-size and hold primitives. ArrayList is dynamic-size, holds only objects, and provides add/remove/contains. Use ArrayList unless you need primitive performance.

Key differences:

  • Size: Array is fixed at creation. ArrayList grows dynamically.
  • Types: Array holds primitives and objects. ArrayList holds only objects (autoboxes primitives).
  • API: Array has .length and []. ArrayList has .size(), .add(), .remove(), .contains(), .sort().
  • Performance: Array is faster for primitives (no boxing). ArrayList is more convenient for everything else.

An array is a fixed row of bank lockers – you cannot add more. An ArrayList is a flexible filing cabinet that grows as you add folders.

Understanding the Concepts

Comparison table

| Feature | Array | ArrayList |
|---|---|---|
| Size | Fixed | Dynamic |
| Primitives | Yes (int[], double[]) | No (uses Integer, Double) |
| Generics | No (int[], not int<>[]) | Yes (ArrayList\) |
| Add/Remove | Manual array copy | .add(), .remove() |
| Performance | Faster for primitives | Slower (autoboxing) |
| Memory | Compact | Overhead (object array + autoboxing) |
| Thread-safe | No | No (use Collections.synchronizedList or CopyOnWriteArrayList) |

When to use which?

JAVA
// Array: fixed-size primitives, performance-critical
int[] dailyTransactions = new int[365];  // 365 days, all ints, no boxing

// ArrayList: dynamic size, objects, convenience
List<Account> accounts = new ArrayList<>();
accounts.add(new Account("SAV2001"));
accounts.add(new Account("CUR3001"));
accounts.remove(0);

Converting between them

JAVA
// Array to List
String[] arr = {"SAV2001", "CUR3001"};
List<String> list = new ArrayList<>(Arrays.asList(arr));

// List to Array
String[] back = list.toArray(new String[0]);

// Primitive array to stream to list
int[] nums = {1, 2, 3};
List<Integer> boxed = Arrays.stream(nums).boxed().collect(Collectors.toList());

What should a senior engineer know?

  • ArrayList internal array doubles in size when full. Default initial capacity is 10.
  • LinkedList vs ArrayList: ArrayList is faster for random access, LinkedList for frequent insertions/removals in the middle.
  • List.of() (Java 9+) creates immutable lists without ArrayList.
  • For large primitive collections, consider Eclipse Collections IntArrayList or HPPC to avoid autoboxing.

What are common mistakes?

A common mistake is not understanding the concept fully before using it in production banking applications.

Wrong approach:

JAVA
package com.bank.service;

public class TransferService {
    public void transfer(String fromAccount, String toAccount, double amount) {
        // WRONG: using double for money
        double balance = getBalance(fromAccount);
        balance = balance - amount;
    }
    private double getBalance(String id) { return 10000.0; }
}

Correct approach:

JAVA
package com.bank.service;

import java.math.BigDecimal;

public class TransferService {
    public void transfer(String fromAccount, String toAccount, BigDecimal amount) {
        // CORRECT: using BigDecimal for money
        BigDecimal balance = getBalance(fromAccount);
        balance = balance.subtract(amount);
    }
    private BigDecimal getBalance(String id) { return new BigDecimal("10000.00"); }
}

Always use BigDecimal for monetary calculations in banking systems to avoid floating-point precision errors.

What are the edge cases?

Edge cases can cause unexpected behavior in banking applications. Here are some to watch for.

JAVA
package com.bank.edge;

public class EdgeCaseDemo {
    public static void main(String[] args) {
        // Edge case 1: null handling
        String accountId = null;
        try {
            System.out.println(accountId.length());
        } catch (NullPointerException e) {
            System.out.println("Null account ID");
        }

        // Edge case 2: empty vs null
        String emptyId = "";
        System.out.println(emptyId.isEmpty());  // true
        System.out.println(emptyId == null);     // false

        // Edge case 3: boundary values
        java.math.BigDecimal zero = java.math.BigDecimal.ZERO;
        java.math.BigDecimal negativeBalance = new java.math.BigDecimal("-0.01");
        System.out.println(zero.compareTo(negativeBalance) > 0);  // true
    }
}
TEXT
Null account ID
true
false
true

Always test with null values, empty strings, boundary values, and negative amounts in banking applications.

What are common interview follow-up questions?

Interviewers often follow up with these related questions:

  • How does this concept apply to a high-throughput banking transaction system?
  • What are the performance implications in a production environment?
  • How would you debug issues related to this concept?
  • What tools would you use to monitor this in production?
  • How does this behave differently in Java 8 vs Java 17+?

When answering follow-up questions, always relate your answer back to practical experience. For example, at National Bank of India, Rajesh debugged a production issue related to this concept by using JFR recordings and heap dumps. Providing concrete examples from banking systems shows the interviewer that you understand both the theory and the practice.

Visual Overview

TEXT
  Array:     int[] a = new int[5];
             fixed, primitives OK, fast, .length

  ArrayList: List<Integer> a = new ArrayList<>();
             dynamic, objects only, autoboxes, .size()/.add()/.remove()

  Rule: use arrays for fixed-size primitives
        use ArrayList for everything else

Key Takeaway

Arrays are fixed-size and hold primitives directly. ArrayList is dynamic-size, holds only objects, and provides rich methods. Use arrays for fixed-size primitive data and performance-critical code. Use ArrayList for everything else.

One sentence to remember: arrays are fixed and fast for primitives, ArrayList is dynamic and convenient for objects.

---

Share
Use ← → arrow keys to navigate