|
@@ -2,8 +2,11 @@
|
|
|
#define HASHMAP_H
|
|
|
|
|
|
#include "utils/Array.h"
|
|
|
+#include "utils/List.h"
|
|
|
#include "utils/StringBuffer.h"
|
|
|
|
|
|
+#include <iostream>
|
|
|
+
|
|
|
template<typename K, typename V, int N_MIN>
|
|
|
class HashMap final {
|
|
|
|
|
@@ -18,21 +21,9 @@ class HashMap final {
|
|
|
static constexpr int CAPACITY = getCapacity();
|
|
|
static constexpr int MASK = CAPACITY - 1;
|
|
|
|
|
|
- Array<bool, CAPACITY> used;
|
|
|
- char keys[sizeof (K) * CAPACITY];
|
|
|
- char values[sizeof (V) * CAPACITY];
|
|
|
-
|
|
|
- const K& getKey(int index) const {
|
|
|
- return reinterpret_cast<const K*> (keys)[index];
|
|
|
- }
|
|
|
-
|
|
|
- V& getValue(int index) {
|
|
|
- return reinterpret_cast<V*> (values)[index];
|
|
|
- }
|
|
|
-
|
|
|
- const V& getValue(int index) const {
|
|
|
- return reinterpret_cast<const V*> (values)[index];
|
|
|
- }
|
|
|
+ Array<int, CAPACITY> used;
|
|
|
+ List<K, CAPACITY> keys;
|
|
|
+ List<V, CAPACITY> values;
|
|
|
|
|
|
enum SearchResult {
|
|
|
FREE_INDEX_FOUND, KEY_FOUND, NOTHING_FOUND
|
|
@@ -50,36 +41,15 @@ class HashMap final {
|
|
|
int base = hash(key);
|
|
|
for(int i = 0; i < CAPACITY; i++) {
|
|
|
int h = (base + i) & MASK;
|
|
|
- if(!used[h]) {
|
|
|
+ if(used[h] == -1) {
|
|
|
return Search(h, FREE_INDEX_FOUND);
|
|
|
- } else if(getKey(h) == key) {
|
|
|
+ } else if(keys[used[h]] == key) {
|
|
|
return Search(h, KEY_FOUND);
|
|
|
}
|
|
|
}
|
|
|
return Search(-1, NOTHING_FOUND);
|
|
|
}
|
|
|
|
|
|
- void copy(const HashMap& other) {
|
|
|
- for(int i = 0; i < other.CAPACITY; i++) {
|
|
|
- if(other.used[i]) {
|
|
|
- used[i] = true;
|
|
|
- new (reinterpret_cast<K*> (keys) + i) K(other.getKey(i));
|
|
|
- new (reinterpret_cast<V*> (values) + i) V(other.getValue(i));
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- void move(HashMap& other) {
|
|
|
- for(int i = 0; i < other.CAPACITY; i++) {
|
|
|
- if(other.used[i]) {
|
|
|
- used[i] = true;
|
|
|
- new (reinterpret_cast<K*> (keys) + i) K(std::move(other.getKey(i)));
|
|
|
- new (reinterpret_cast<V*> (values) + i) V(std::move(other.getValue(i)));
|
|
|
- }
|
|
|
- }
|
|
|
- other.clear();
|
|
|
- }
|
|
|
-
|
|
|
template<typename H>
|
|
|
static int hash(const H& key) {
|
|
|
return key.hashCode();
|
|
@@ -91,33 +61,31 @@ class HashMap final {
|
|
|
|
|
|
public:
|
|
|
|
|
|
- HashMap() : used(false) {
|
|
|
+ HashMap() : used(-1) {
|
|
|
}
|
|
|
|
|
|
- ~HashMap() {
|
|
|
- clear();
|
|
|
- }
|
|
|
-
|
|
|
- HashMap(const HashMap& other) : used(false) {
|
|
|
- copy(other);
|
|
|
+ HashMap(const HashMap& other) : used(other.used), keys(other.keys), values(other.values) {
|
|
|
}
|
|
|
|
|
|
HashMap& operator=(const HashMap& other) {
|
|
|
if(&other != this) {
|
|
|
- clear();
|
|
|
- copy(other);
|
|
|
+ used = other.used;
|
|
|
+ keys = other.keys;
|
|
|
+ values = other.values;
|
|
|
}
|
|
|
return *this;
|
|
|
}
|
|
|
|
|
|
- HashMap(HashMap&& other) : used(false) {
|
|
|
- move(other);
|
|
|
+ HashMap(HashMap&& other) : used(other.used), keys(std::move(other.keys)), values(std::move(other.values)) {
|
|
|
+ other.used.fill(-1);
|
|
|
}
|
|
|
|
|
|
HashMap& operator=(HashMap&& other) {
|
|
|
if(&other != this) {
|
|
|
- clear();
|
|
|
- move(other);
|
|
|
+ used = std::move(other.used);
|
|
|
+ keys = std::move(other.keys);
|
|
|
+ values = std::move(other.values);
|
|
|
+ other.used.fill(-1);
|
|
|
}
|
|
|
return *this;
|
|
|
}
|
|
@@ -126,9 +94,9 @@ public:
|
|
|
bool tryEmplace(const K& key, Args&&... args) {
|
|
|
Search s = searchIndex(key);
|
|
|
if(s.result == FREE_INDEX_FOUND) {
|
|
|
- used[s.index] = true;
|
|
|
- new (reinterpret_cast<K*> (keys) + s.index) K(key);
|
|
|
- new (reinterpret_cast<V*> (values) + s.index) V(args...);
|
|
|
+ used[s.index] = keys.getLength();
|
|
|
+ keys.add(key);
|
|
|
+ values.add(args...);
|
|
|
return false;
|
|
|
}
|
|
|
return true;
|
|
@@ -137,11 +105,11 @@ public:
|
|
|
HashMap& add(const K& key, const V& value) {
|
|
|
Search s = searchIndex(key);
|
|
|
if(s.result == KEY_FOUND) {
|
|
|
- getValue(s.index) = value;
|
|
|
+ values[used[s.index]] = value;
|
|
|
} else if(s.result == FREE_INDEX_FOUND) {
|
|
|
- used[s.index] = true;
|
|
|
- new (reinterpret_cast<K*> (keys) + s.index) K(key);
|
|
|
- new (reinterpret_cast<V*> (values) + s.index) V(value);
|
|
|
+ used[s.index] = keys.getLength();
|
|
|
+ keys.add(key);
|
|
|
+ values.add(value);
|
|
|
}
|
|
|
return *this;
|
|
|
}
|
|
@@ -149,23 +117,23 @@ public:
|
|
|
HashMap& add(const K& key, const V&& value) {
|
|
|
Search s = searchIndex(key);
|
|
|
if(s.result == KEY_FOUND) {
|
|
|
- getValue(s.index) = std::move(value);
|
|
|
+ values[used[s.index]] = std::move(value);
|
|
|
} else if(s.result == FREE_INDEX_FOUND) {
|
|
|
- used[s.index] = true;
|
|
|
- new (reinterpret_cast<K*> (keys) + s.index) K(key);
|
|
|
- new (reinterpret_cast<V*> (values) + s.index) V(std::move(value));
|
|
|
+ used[s.index] = keys.getLength();
|
|
|
+ keys.add(key);
|
|
|
+ values.add(std::move(value));
|
|
|
}
|
|
|
return *this;
|
|
|
}
|
|
|
|
|
|
const V& search(const K& key, const V& notFound) const {
|
|
|
Search s = searchIndex(key);
|
|
|
- return s.result == KEY_FOUND ? getValue(s.index) : notFound;
|
|
|
+ return s.result == KEY_FOUND ? values[used[s.index]] : notFound;
|
|
|
}
|
|
|
|
|
|
V& search(const K& key, V& notFound) {
|
|
|
Search s = searchIndex(key);
|
|
|
- return s.result == KEY_FOUND ? getValue(s.index) : notFound;
|
|
|
+ return s.result == KEY_FOUND ? values[used[s.index]] : notFound;
|
|
|
}
|
|
|
|
|
|
bool contains(const K& key) const {
|
|
@@ -173,15 +141,9 @@ public:
|
|
|
}
|
|
|
|
|
|
HashMap& clear() {
|
|
|
- K* k = reinterpret_cast<K*> (keys);
|
|
|
- V* v = reinterpret_cast<V*> (values);
|
|
|
- for(int i = 0; i < CAPACITY; i++) {
|
|
|
- if(used[i]) {
|
|
|
- k[i].~K();
|
|
|
- v[i].~V();
|
|
|
- }
|
|
|
- }
|
|
|
- used.fill(false);
|
|
|
+ keys.clear();
|
|
|
+ values.clear();
|
|
|
+ used.fill(-1);
|
|
|
return *this;
|
|
|
}
|
|
|
|
|
@@ -190,12 +152,12 @@ public:
|
|
|
s.append("[");
|
|
|
bool c = false;
|
|
|
for(int i = 0; i < CAPACITY; i++) {
|
|
|
- if(!used[i]) {
|
|
|
+ if(used[i] == -1) {
|
|
|
continue;
|
|
|
} else if(c) {
|
|
|
s.append(", ");
|
|
|
}
|
|
|
- s.append(getKey(i)).append(" = ").append(getValue(i));
|
|
|
+ s.append(keys[used[i]]).append(" = ").append(values[used[i]]);
|
|
|
c = true;
|
|
|
}
|
|
|
s.append("]");
|