Starting from API version 26.0.0, a high-performance HashMap data structure is available for single-threaded scenarios.
For details about the APIs, please refer to the API Reference.
| API | Description |
|---|---|
| FAST_ErrorCode HMS_FAST_Hashmap_Create (FAST_HashmapHandle* handle, HMS_FAST_Hashmap_HashFunc hasher, HMS_FAST_Hashmap_KeyEqualFunc equaler) | Creates a HashMap instance. |
| void HMS_FAST_Hashmap_Destroy (FAST_HashmapHandle handle) | Destroys a HashMap instance. |
| FAST_ErrorCode HMS_FAST_Hashmap_Insert (FAST_HashmapHandle handle, const FAST_HashmapKeyPtr key, const FAST_HashmapValuePtr value, FAST_HashmapValuePtr* originValue) | Inserts a given key-value pair into a HashMap. If the key already exists, the existing value is overwritten with value, and the address of the original value is stored in originValue. |
| FAST_ErrorCode HMS_FAST_Hashmap_Find (FAST_HashmapHandle handle, const FAST_HashmapKeyPtr key, FAST_HashmapValuePtr* value) | Retrieves the value associated with the given key and stores the value in value. |
| FAST_ErrorCode HMS_FAST_Hashmap_Erase (FAST_HashmapHandle handle, const FAST_HashmapKeyPtr key, FAST_HashmapKeyPtr* originKey, FAST_HashmapValuePtr* originValue) | Deletes the input key from the given HashMap and saves the addresses of the corresponding key and value into originKey and originValue, respectively. |
| FAST_ErrorCode HMS_FAST_Hashmap_TryInsert (FAST_HashmapHandle handle, const FAST_HashmapKeyPtr key, const FAST_HashmapValuePtr value) | Inserts a given key-value pair into a HashMap. If the key already exists, no operation is performed. |
| size_t HMS_FAST_Hashmap_Size (FAST_HashmapHandle handle) | Returns the number of elements in a HashMap. |
| void HMS_FAST_Hashmap_Clear (FAST_HashmapHandle handle) | Deletes all elements from a HashMap. |
| size_t HMS_FAST_Hashmap_EraseIf (FAST_HashmapHandle handle, HMS_FAST_Hashmap_HookFunc condFunc, void* condCtx, HMS_FAST_Hashmap_HookFunc freeFunc, void* freeCtx) | Deletes all elements that meet the specified conditions from a HashMap and releases the memory in the custom manner. |
| void HMS_FAST_Hashmap_Traverse (FAST_HashmapHandle handle, HMS_FAST_Hashmap_HookFunc condFunc, void* condCtx, HMS_FAST_Hashmap_HookFunc workFunc, void* workCtx) | Traverses a HashMap and modifies all key-value pairs that meet the specified conditions in the custom manner. |
Link the related dynamic library in the CMake script.
find_library(
lib_fast_collection
NAMES fast_collection
)
target_link_libraries(entry PRIVATE ${lib_fast_collection}) Define how to calculate hash values and compare keys.
#include "FASTKit/fast_collections_hashmap.h"
// Define how to calculate hash values and compare keys.
uint64_t custom_hash_int(const FAST_HashmapKeyPtr key) {
static std::hash<int> hasher;
int* intKey = (int*)key;
return hasher(*intKey);
}
int32_t custom_equal_int(const FAST_HashmapKeyPtr key1, const FAST_HashmapKeyPtr key2) {
int* intKey1 = (int*)key1;
int* intKey2 = (int*)key2;
return (*intKey1) == (*intKey2);
}
// Customize the deletion condition.
int32_t custom_erase_cond(FAST_HashmapKeyPtr key, FAST_HashmapValuePtr val, void* context) {
return 1;
}
// Free the memory held by the key and value pointers.
int32_t custom_free(FAST_HashmapKeyPtr key, FAST_HashmapValuePtr val, void* context) {
int* intKey = (int*)key;
int* intVal = (int*)val;
delete intKey;
delete intVal;
return 0;
}
// Customize the modification condition. You can also pass nullptr to modify all elements.
int32_t custom_modify_cond(FAST_HashmapKeyPtr key, FAST_HashmapValuePtr val, void* context) {
return 1;
}
int32_t custom_work(FAST_HashmapKeyPtr key, FAST_HashmapValuePtr val, void* context) {
int* intVal = (int*)val;
int* intCtx = (int*)context;
*intVal += (*intCtx);
return 1;
}
static napi_value RunHashmap(napi_env env, napi_callback_info info)
{
// Create a HashMap.
FAST_HashmapHandle handle;
HMS_FAST_Hashmap_HashFunc hasher = &custom_hash_int;
HMS_FAST_Hashmap_KeyEqualFunc equaler = &custom_equal_int;
int ret = HMS_FAST_Hashmap_Create(&handle, hasher, equaler);
// Initialize an empty HashMap and insert elements into it.
const int size = 10;
int keys[size] = {1,2,3,4,5,6,7,8,9,10};
int vals[size] = {1,2,3,4,5,6,7,8,9,10};
for (int i = 0; i < size; ++i) {
ret = HMS_FAST_Hashmap_Insert(
handle,
(FAST_HashmapKeyPtr)&(keys[i]),
(FAST_HashmapValuePtr)&(vals[i]),
nullptr
);
} // After the insertion, the HashMap should contain {1: 1, 2: 2, ..., 10: 10}.
// Use insert to overwrite the existing key. If tryInsert is used, the existing key will not be overwritten.
int key2 = 1;
int val2 = 2;
int* originVal0;
ret = HMS_FAST_Hashmap_Insert(
handle,
(FAST_HashmapKeyPtr)&key2,
(FAST_HashmapValuePtr)&val2,
(FAST_HashmapValuePtr*)&originVal0
); // {1: 2, ...}, and originVal0 == &vals[0]
// Use the key to search for the corresponding value and save the result in the input pointer. When using this API, you need to verify the return value ret.
// If the value of ret is not FAST_ERROR_CODE_SUCCESS, the value obtained by res is invalid.
int targetKey = 1;
int* res;
ret = HMS_FAST_Hashmap_Find(
handle,
(FAST_HashmapKeyPtr)&targetKey,
(FAST_HashmapValuePtr*)&res
); // (*res) == 2
// Remove the key-value pair associated with the key from the HashMap and retrieve the associated memory addresses.
// You can use originKey/Val to obtain the address of the pre-inserted element for memory management. You can also use nullptr as the input parameter.
int* originKey1;
int* originVal1;
int deleteKey = 1;
ret = HMS_FAST_Hashmap_Erase(
handle,
(FAST_HashmapKeyPtr)&deleteKey,
(FAST_HashmapKeyPtr*)&originKey1,
(FAST_HashmapValuePtr*)&originVal1
); // originKey1 == &keys[0] && originVal1 == &val2
//Query the number of elements in the HashMap.
size_t curSize = HMS_FAST_Hashmap_Size(handle); // curSize == 9
// Clear all elements in the HashMap.
HMS_FAST_Hashmap_Clear(handle);
curSize = HMS_FAST_Hashmap_Size(handle); // curSize == 0
for (int i = 0; i < 6; i++) {
int* key = new int{i};
int* val = new int{i};
ret = HMS_FAST_Hashmap_Insert(
handle,
(FAST_HashmapKeyPtr)key,
(FAST_HashmapValuePtr)val,
nullptr
);
} // {0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5}
// Use the Traverse API to perform the custom_work operation on the elements that meet the custom_modify_cond condition.
int context = 10;
HMS_FAST_Hashmap_Traverse(
handle,
(HMS_FAST_Hashmap_HookFunc)&custom_modify_cond,
nullptr,
(HMS_FAST_Hashmap_HookFunc)&custom_work,
(void*)&context
); // {0: 10, 1: 11, 2: 12, 3: 13, 4: 14, 5: 15}
// Use the EraseIf API to delete all key-value pairs that meet the custom_erase_cond condition and use custom_free to clear the corresponding memory.
ret = HMS_FAST_Hashmap_EraseIf(
handle,
(HMS_FAST_Hashmap_HookFunc)&custom_erase_cond,
nullptr,
(HMS_FAST_Hashmap_HookFunc)&custom_free,
nullptr
); // size == 0 && ret == 6
// Destroy the HashMap.
HMS_FAST_Hashmap_Destroy(handle);
return 0;
} Memory management: HashMaps only store pointers and does not manage memory. Callers must manage the memory pointed to by keys and values to ensure that the memory remains valid throughout the entry lifetime.
Single-threaded scenario: This HashMap is designed for single-threaded scenarios and does not support concurrent access from multiple threads. For multithreaded support, use ConcurrentHashMap.
Return value verification: All APIs that return FAST_ErrorCode should check the return value and use output parameters only after the operation succeeds.
Callback functions: Callback functions in Traverse and EraseIf are executed while the internal lock is held. Avoid blocking or re-entering HashMap APIs in callbacks.