ArrayList / HashMap
Zig's standard library provides ArrayList for dynamic arrays and HashMap (and AutoHashMap) for hash maps. Both take an allocator during initialization, making memory allocation and deallocation responsibilities explicit. ArrayList automatically expands its internal buffer as elements are added, and HashMap stores key-value pairs with O(1) average time complexity.
Syntax
// -----------------------------------------------
// ArrayList — dynamic array
// -----------------------------------------------
// Initialize (pass an allocator)
var list = std.ArrayList(ElementType).init(allocator);
defer list.deinit(); // frees the internal buffer when the scope exits
// Append to the end
try list.append(value);
// Insert at a specific position (index, value)
try list.insert(index, value);
// Remove an element (by index, preserves order)
_ = list.orderedRemove(index);
// Remove an element (by index, swaps with last element — faster)
_ = list.swapRemove(index);
// Check length and capacity
list.items.len // current number of elements
list.capacity // internal buffer capacity
// Access as a slice
for (list.items) |item| { /* … */ }
// -----------------------------------------------
// AutoHashMap — hash map with automatic hash function
// -----------------------------------------------
// Initialize (pass key type, value type, and allocator)
var map = std.AutoHashMap(KeyType, ValueType).init(allocator);
defer map.deinit(); // frees the internal table when the scope exits
// Add or update an entry
try map.put(key, value);
// Get an entry (returns null if not found)
const val = map.get(key); // ?ValueType
// Remove an entry
_ = map.remove(key); // returns bool indicating whether deletion succeeded
// Check if a key exists
const exists = map.contains(key); // bool
// Iterate over all entries
var it = map.iterator();
while (it.next()) |entry| {
_ = entry.key_ptr.*; // key
_ = entry.value_ptr.*; // value
}
// -----------------------------------------------
// StringHashMap — hash map with string keys
// -----------------------------------------------
var smap = std.StringHashMap(ValueType).init(allocator);
defer smap.deinit();
try smap.put("key_string", value);
Method Reference
| Method / Property | Target | Description |
|---|---|---|
init(allocator) | ArrayList / HashMap | Initializes the collection with an allocator. |
deinit() | ArrayList / HashMap | Frees the internal buffer or table. Typically used with defer. |
append(value) | ArrayList | Appends an element to the end. Automatically expands capacity if needed. |
insert(index, value) | ArrayList | Inserts an element at the specified index. Shifts subsequent elements backward. |
orderedRemove(index) | ArrayList | Removes an element while preserving order. Takes O(n) time. |
swapRemove(index) | ArrayList | Swaps the element with the last element, then removes it. O(1) but does not preserve order. |
items | ArrayList | The internal slice ([]T). Use this for for loops and index access. |
put(key, value) | HashMap | Adds or overwrites a key-value pair. |
get(key) | HashMap | Returns the value for the key as ?T. Returns null if the key does not exist. |
remove(key) | HashMap | Removes the entry and returns a bool indicating whether deletion succeeded. |
contains(key) | HashMap | Returns a bool indicating whether the key exists. |
count() | HashMap | Returns the number of registered entries. |
iterator() | HashMap | Returns an iterator for traversing all entries. |
getOrPut(key) | HashMap | Reserves an entry if the key does not exist. The result provides .found_existing and .value_ptr. |
Sample Code
collection.zig
// collection.zig — basic example of ArrayList and HashMap
// Demonstrates dynamic array operations with ArrayList
// and key-value management with AutoHashMap / StringHashMap
const std = @import("std");
pub fn main() !void {
const stdout = std.io.getStdOut().writer();
// Use GeneralPurposeAllocator
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
// -----------------------------------------------
// ArrayList — dynamic list of names
// -----------------------------------------------
try stdout.print("=== Member List (ArrayList) ===\n\n", .{});
// Initialize an ArrayList of []const u8
var members = std.ArrayList([]const u8).init(allocator);
defer members.deinit();
// Add members
try members.append("user1");
try members.append("user2");
try members.append("user3");
try members.append("user4");
try members.append("user5");
try stdout.print("Count: {d}\n", .{members.items.len});
try stdout.print("All members:\n", .{});
for (members.items, 0..) |name, i| {
try stdout.print(" [{d}] {s}\n", .{ i, name });
}
// Insert a new member at the beginning (index 0)
try members.insert(0, "user0");
try stdout.print("\nAfter inserting user0 at the beginning:\n", .{});
for (members.items, 0..) |name, i| {
try stdout.print(" [{d}] {s}\n", .{ i, name });
}
// Remove the element at index 2, preserving order
const removed = members.orderedRemove(2);
try stdout.print("\nAfter removing index 2 ({s}):\n", .{removed});
for (members.items, 0..) |name, i| {
try stdout.print(" [{d}] {s}\n", .{ i, name });
}
// -----------------------------------------------
// AutoHashMap — item grade management
// Key: u8 (ID), Value: struct
// -----------------------------------------------
try stdout.print("\n=== Item Grade Table (AutoHashMap) ===\n\n", .{});
// Struct holding item information
const Item = struct {
name: []const u8, // name
grade: []const u8, // grade
power: u32, // power level (arbitrary unit)
};
// Key: u8 (ID), Value: Item
var grade_map = std.AutoHashMap(u8, Item).init(allocator);
defer grade_map.deinit();
// Add entries
try grade_map.put(1, .{ .name = "item_s1", .grade = "S", .power = 9999 });
try grade_map.put(2, .{ .name = "item_s2", .grade = "S", .power = 9500 });
try grade_map.put(3, .{ .name = "item_s3", .grade = "S", .power = 9200 });
try grade_map.put(4, .{ .name = "item_a1", .grade = "A", .power = 7000 });
try grade_map.put(5, .{ .name = "item_a2", .grade = "A", .power = 6500 });
try stdout.print("Count: {d}\n\n", .{grade_map.count()});
// Retrieve by ID (get returns ?Item)
const target_id: u8 = 4;
if (grade_map.get(target_id)) |s| {
try stdout.print("Item with ID {d}:\n", .{target_id});
try stdout.print(" Name : {s}\n", .{s.name});
try stdout.print(" Grade: {s}\n", .{s.grade});
try stdout.print(" Power: {d}\n", .{s.power});
}
// Look up a non-existent ID
const missing_id: u8 = 99;
const missing = grade_map.get(missing_id);
try stdout.print("\nSearch result for ID {d}: {?}\n", .{ missing_id, missing });
// Traverse all entries with an iterator
try stdout.print("\n--- All items ---\n", .{});
var it = grade_map.iterator();
while (it.next()) |entry| {
const id = entry.key_ptr.*;
const s = entry.value_ptr.*;
try stdout.print(" ID {d}: {s} ({s}) power {d}\n", .{ id, s.name, s.grade, s.power });
}
// Remove an entry
_ = grade_map.remove(2);
try stdout.print("\nCount after removing ID 2: {d}\n", .{grade_map.count()});
// -----------------------------------------------
// StringHashMap — keyword frequency count
// Key: string, Value: u32 (occurrence count)
// -----------------------------------------------
try stdout.print("\n=== Keyword Count (StringHashMap) ===\n\n", .{});
var term_count = std.StringHashMap(u32).init(allocator);
defer term_count.deinit();
// Keyword list
const terms = [_][]const u8{
"attack", "critical", "attack",
"defense", "critical", "item_x",
"attack", "item_x", "defense",
"critical",
};
// Increment counts using getOrPut
for (terms) |term| {
// If the key does not exist, value_ptr is set to 0
const result = try term_count.getOrPut(term);
if (!result.found_existing) {
result.value_ptr.* = 0; // initialize to 0 on first occurrence
}
result.value_ptr.* += 1; // increment count
}
try stdout.print("Keyword occurrences:\n", .{});
var term_it = term_count.iterator();
while (term_it.next()) |entry| {
try stdout.print(" {s}: {d}\n", .{ entry.key_ptr.*, entry.value_ptr.* });
}
}
zig run collection.zig === Member List (ArrayList) === Count: 5 All members: [0] user1 [1] user2 [2] user3 [3] user4 [4] user5 After inserting user0 at the beginning: [0] user0 [1] user1 [2] user2 [3] user3 [4] user4 [5] user5 After removing index 2 (user2): [0] user0 [1] user1 [2] user3 [3] user4 [4] user5 === Item Grade Table (AutoHashMap) === Count: 5 Item with ID 4: Name : item_a1 Grade: A Power: 7000 Search result for ID 99: null --- All items --- ID 1: item_s1 (S) power 9999 ID 2: item_s2 (S) power 9500 ID 3: item_s3 (S) power 9200 ID 4: item_a1 (A) power 7000 ID 5: item_a2 (A) power 6500 Count after removing ID 2: 4 === Keyword Count (StringHashMap) === Keyword occurrences: attack: 3 critical: 3 defense: 2 item_x: 2
Notes
Zig's ArrayList is the equivalent of C++'s std::vector or Rust's Vec — a dynamic array that you access through its .items slice just like a regular array. For removing elements, you have two options: orderedRemove (preserves order, O(n)) and swapRemove (changes order, O(1)). For HashMap, Zig provides AutoHashMap for types supported by std.hash_map.AutoContext (such as integers and structs), and StringHashMap for string keys. getOrPut reserves a new entry if the key does not exist and lets you check whether the entry already existed via the found_existing flag — this allows you to handle both initialization and incrementing in a single call. For both collections, registering deinit() with defer is the standard pattern. For more on allocators, see Allocator Basics.
If you find any errors or copyright issues, please contact us.