UnsafeHashMap

Dense hash map acting as a mostly-compatible (even if unsafe) AA replacement.

The mechanism used to override hashing and comparison functions is the same as for standard AAs. Unlike AA's, however, this hash table does NOT guarantee that references to its internal storage will be kept stable between rehashes, which may also be caused by insertion operations.

Constructors

this
this(size_t capacity)

Initializes a new table with a certain preallocated capacity.

Members

Functions

add
err_t add(Key element)

Adds an element to the hash set; may rehash.

byKey
auto byKey()
byKeyValue
auto byKeyValue()
byValue
auto byValue()

Can be used to iterate over this table's entries (but iteration order is unspecified).

clear
void clear()

Removes all elements from the hash table, without changing its capacity.

dispose
void dispose()

Clears and frees the table's internal storage.

dup
UnsafeHashMap dup(err_t error)
UnsafeHashMap dup()

Creates an independent copy of a hash table.

get
bool get(const(Key) needle, inout(Key)* keyp, inout(Value)* valp)

Looks up an entry in the table's internal storage.

opBinaryRight
inout(Key)* opBinaryRight(const(Key) key)

Returns a pointer to a matching KEY in the table, or null

opEquals
bool opEquals(const(UnsafeHashMap) other)

Structural equality comparison.

opIndex
inout(Value) opIndex(const(Key) key)

Returns (a ref to) the value associated with a given key.

opIndexAssign
err_t opIndexAssign(Value value, Key key)

Upserts an entry in the hash table. May cause a rehash.

rehash
err_t rehash(size_t newCapacity)
err_t rehash()

Rehashes the table.

remove
bool remove(const(Key) key)

Removes a key's entry from the table.

require
Value require(Key key, const(Create) create, err_t error)
Value require(Key key, const(Create) create)

Looks up a key's entry, inserting one if not found (may rehash).

toHash
size_t toHash()

Structural hash of this table.

update
Value update(Key key, const(Create) create, const(Update) update, err_t error)
Value update(Key key, const(Create) create, const(Update) update)

Looks up a key's entry in the table, then either updates it or creates a new one (may rehash).

Properties

capacity
size_t capacity [@property getter]

Entries the table can hold without being rehashed.

length
size_t length [@property getter]

Number of entries currently being used in the hash table.

Examples

This type optimizes storage when value types are zero-sized (e.g. for UnsafeHashSet):

alias NonZero = long;
alias Zero = void[0];
static assert(UnsafeHashMap!(char, Zero).sizeof < UnsafeHashMap!(char, NonZero).sizeof);

Consider using scope(exit) to ensure hash table memory doesn't leak.

UnsafeHashMap!(char, long) outer;
{
    auto inner = UnsafeHashMap!(char, long)(42);
    scope(exit) inner.dispose();
    outer = inner; // but be careful with shallow copies
}
// outer.dispose(); // would have caused a double free: `dispose` is unsafe!

Basic usage:

HashMap!(char, long) table;
assert(table.length == 0);

assert('a' !in table);
table['a'] = 0; // inserts
assert('a' in table);
table['a'] = 1; // updates
assert(table.length == 1);

assert('a' in table);
assert(table.remove('a') == true);
assert('a' !in table);
assert(table.remove('a') == false);
assert(table.length == 0);

static immutable reverse = ['a', 'b', 'c', 'd', 'e'];
foreach (i, c; reverse) table[c] = i + 1;
table.rehash(); // must preserve elements
assert(table.length == reverse.length);
foreach (key; table.byKey) assert(key == reverse[table[key] - 1]);
foreach (val; table.byValue) assert(val == table[reverse[val - 1]]);

const cap = table.capacity;
table.clear(); // preserves capacity
assert(table.length == 0);
assert(table.capacity == cap);

Sligthly more advanced example:

import core.stdc.ctype : isalnum;
import eris.util : empty;

bool isAnagram(const(string) a, const(string) b) {
    // count letter frequencies in A
    HashMap!(char, long) letters;
    foreach (c; a) {
        if (!c.isalnum) continue;
        const freq = letters.get(c, () => 0L);
        letters[c] = freq + 1;
    }
    // check if they match B's
    foreach (c; b) {
        if (!c.isalnum) continue;
        const freq = letters.update(c, () => -1L, (long f) => f - 1);
        if (freq < 0) return false;
        else if (freq == 0) letters.remove(c);
    }
    return letters.empty;
}

assert(  isAnagram("tom marvolo riddle", "i am lord voldemort") );
assert( !isAnagram("aabaa", "bbabb")                            );

See Also

The safer HashMap