High-performance array-based list using static shared storage per type. In most cases, a LinkedList is a better choice due to its flexibility. This data structure is only recommended for performance-critical code and requires careful use to avoid fragmentation.
ArrayList is faster than LinkedList for:
LinkedList is better for:
Each ArrayList
Choose wisely based on how many types you have.
PRESIZE, DON’T RESIZE Bad: new ArrayList
Why: Resize operations copy ALL elements to new memory. Expensive!
REUSE, DON’T RECREATE Bad: In loop let temp = new ArrayList<int>() ... destroy temp Good: let temp = new ArrayList<int>() ... temp.clear() in loop
Why: Allocation/Deallocation is moderately expensive and causes fragmentation
ORDERED REMOVAL IS SLOW Bad: list.removeAt(i) // O(n) - shifts all elements Good: list.removeAtUnordered(i) // O(1) - swaps with last element
Only use removeAtUnordered() if order doesn’t matter
ITERATE BY INDEX Good: for i = 0 to list.size()-1 // Zero allocation Good: list[i] // Indexing operator
ArrayList has no iterator by design - index loops keep hot paths allocation-free.
AVOID FREQUENT INSERTS AT START Bad: list.addtoStart(x) // O(n) every time Good: Use LinkedList or add in reverse order
Operation | ArrayList | LinkedList | Notes ——————-|———–|————|————————— add(elem) | O(1)* | O(1) | *O(n) on resize! addtoStart(elem) | O(n) | O(1) | Shifts all elements get(index) | O(1) | O(n) | Major ArrayList advantage removeAt(index) | O(n) | O(1) | Shifts remaining elements removeAtUnordered | O(1) | N/A | Doesn’t preserve order Iterate all | Faster | Fast | LinkedList does double the work, but is still fast Memory per element | 1 slot | 3 slots | Element + 2 pointers Create/destroy | Varies | High | AL might need memory management, LL needs to process Nodes
ArrayList uses section allocation in a shared static array per type. Destroyed lists return sections to a free pool for reuse. Free sections are compacted to reduce fragmentation.
Fragmentation occurs when lists grow - the old section becomes a gap. This is why presizing matters: growth = copy to new location = wasted space.
Hard limit (wc3 / Jass native target): the shared store is a fixed-size array, so it is bounded by JASS_MAX_ARRAY_SIZE total slots per type across all live instances; exceeding it raises an error. On the Lua target the store is a dynamically growing table, so the cap does not apply - allocateStorage branches on the magic isLua constant and skips the error. ArrayList’s added value on Lua is keeping element types static instead of relying on typecasting.
public class ArrayList<T:>
public interface ArrayListPredicate<T:>
public interface ALItrClosure<T:>
public interface ArrayListUpdater<T:>
public interface MapClosure<T:, Q:>
public interface FoldClosure<T:, Q:>
public interface Comparator<T:>
public function asArrayList<T:>(vararg T ts) returns ArrayList<T>
public function ArrayList<int>.sort()
public function ArrayList<real>.sort()
public function ArrayList<string>.sort()
public function ArrayList<string>.joinBy(string separator) returns string
Joins elements from a string list into one string using a separator
public function ArrayList<string>.join() returns string
Joins elements from a string list into one string
public function ArrayList<T>.op_index<T>(int index) returns T
public function ArrayList<T>.op_indexAssign<T>(int index, T value)