HashMap
Overview
A HashMap is a specialized data structure that contains key-value pairs.
HashMaps provide (near) constant-time lookup for keys, making them highly efficient at finding the value associated with a specific key - even if there is a very large amount of keys.
See Wikipedia to learn more about the underlying technology.
While HashMaps and Arrays share many traits (and SQF command names), there are important differences and HashMaps must not be considered as some sort of new or improved replacement for the Array.
Working with HashMaps
Key Types
Because of the requirement for the keys to be hashable (and constant), not all Data Types can be used as keys.
Supported types are limited to:
Creating a HashMap
// Example of an empty HashMap private _myMap = createHashMap; count _myMap; // returns 0 // Example of a prefilled HashMap private _myFilledMap = createHashMapFromArray [["a",1], ["b",2], ["c", 3]]; count _myFilledMap; // returns 3
Setting an element
private _myMap = createHashMap; _myMap set [1, "hello there"]; // _myMap is [[1, "hello there"]]
Inserting an element with a key that already exists inside the HashMap will overwrite the existing key.
private _myMap = createHashMapFromArray [["a",1], ["b",2]]; _overwritten = _myMap set ["a", 1337]; // _myMap is now [["a",1337], ["b",2]] and _overwritten is true
Getting an element
Values are retrieved by their key:
private _myMap = createHashMapFromArray [["a",1], ["b",2]]; _myMap get "a"; // returns 1 _myMap get "z"; // returns Nothing _myMap getOrDefault ["z", "NotFound"]; // returns "NotFound"
Removing an element
You can remove (delete) elements from the HashMap using deleteAt with the element's key:
private _myMap = createHashMapFromArray [["a",1], ["b",2]]; _myMap deleteAt "b"; // _myMap is "a",1
Checking if an element exists
You can check if a key is present in the HashMap using the in command:
private _myMap = createHashMapFromArray [["a",1], ["b",2]]; "a" in _myMap; // returns true "z" in _myMap; // returns false
Counting elements
The count command can be used to return the number of key-value pairs stored in the HashMap:
private _myMap = createHashMapFromArray [["a",1], ["b",2]]; count _myMap ; // returns 2
Retrieving keys
You can retrieve an Array of all keys in the HashMap using the keys command:
private _myMap = createHashMapFromArray [["a",1], ["b",2]]; keys _myMap; // returns ["a", "b"]
HashMap variables
A HashMap variable is a reference to the HashMap (see Wikipedia); this means that if the HashMap is edited, all scripts and functions using this HashMap will see the changes.
private _myMap = createHashMapFromArray [["a",1], ["b",2], ["c",3]]; private _myNewMap = _myMap; _myMap set ["z", 4]; _myNewMap get "z"; // will be 4
A HashMap set through setVariable does not need to be assigned again:
player setVariable ["myMap", createHashMapFromArray [["a",1], ["b",2], ["c",3]]]; private _myMap = player getVariable "myMap"; _myMap set ["z", 4]; player getVariable "myMap"; // is [["a",1], ["b",2], ["c",3], ["z",4]]
Copying a HashMap
private _myMap = createHashMapFromArray [["a",1], ["b",2]]; private _myNewMap = _myMap; _myMap set ["a", 1337]; _myNewMap get "a"; // will be 1337
In order to avoid this behaviour, copy the HashMap with + (plus):
private _myMap = createHashMapFromArray [["a",1], ["b",2]]; private _myNewMap = +_myMap; _myMap set ["a", 1337]; _myNewMap get "a"; // still 1
Arrays stored as key or value in the HashMap will also be deep-copied.
Advanced usage
Iterating through a HashMap
In general, HashMaps have to be considered unordered. While iterating through them is possible with forEach, it is less efficient than looping through Arrays.
private _myMap = createHashMapFromArray [["a",1], ["b",2]]; { systemChat str [_x, _y] } forEach _myMap;
When iterating through a HashMap with forEach, _x contains the key of the current element and _y contains the corresponding value.
Common errors
Scalar Key precision
Numbers in Arma 3 are floating point numbers, and because there are gaps between floating point numbers, rounding is necessary - see also Wikipedia. For example, 87654316, 87654317, 87654318, 87654319, 87654320, 87654321, 87654322, 87654323 and 87654324 will all be rounded to and treated as the same value by the game engine (because the actual value of each of these numbers can not be represented as an Arma 3 floating point number). Similar problems occur with fractional numbers:
// This will return false: (0.3 + 0.4 == 0.7)
This means that using very large numbers or fractional numbers as HashMap keys has to be done cautiously to avoid accidentally overwriting existing keys.