Quellcode durchsuchen

simpler hash map implementation by using ints as pointers and lists

Kajetan Johannes Hammerle vor 3 Jahren
Ursprung
Commit
7781d07751
1 geänderte Dateien mit 37 neuen und 75 gelöschten Zeilen
  1. 37 75
      utils/HashMap.h

+ 37 - 75
utils/HashMap.h

@@ -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("]");