Can `StringHashMap` be used without persistent key strings?

As far as I can tell, StringHashMap requires the key string buffer to remain valid for the lifetime of the map. E.g.

const key = try allocPrint(allocator, "...", .{});
try map.put(key, value);

I never need to read the key string back out of the map though. Is it possible to use the map in such a way that the key buffer doesn’t need to be persisted, only its hash? E.g.

var key_buf: [n]u8 = undefined;
const key = try bufPrint(&key_buf, "...", .{});
try map.put(key, value);

I see there are a bunch of variant methods with “context” and “adapted” in the names. I don’t understand what those do yet, so maybe what I want can be done with those somehow?

Not in general, since having the hash is not always enough to check for a match – think of hash collisions, in which case you do need to compare with the full string.

1 Like

You can make it a bit easier for yourself by using an ArenaAllocator. That way you don’t need to manually free all the strings you allocated, instead you only need to free the arena.

1 Like

2 tips:

  1. You can use a short-lived key with getOrPut, and then only if the key did not already exist, overwrite the key with a longer-lived key:
const gop = try map.getOrPut(short_lived_key);
if (!gop.found_existing) {
    errdefer map.remove(short_lived_key);
    gop.key_ptr.* = try allocatior.dupe(u8, short_lived_key);
    gop.value_ptr.* = initTheValue();
}
  1. You can use an adapted hash map to work with more advanced string memory management strategies, such as a string table: How to use hash map contexts to save memory when doing a string table - Zig NEWS
7 Likes