HashMap.h 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. #ifndef HASHMAP_H
  2. #define HASHMAP_H
  3. #include "utils/Array.h"
  4. #include "utils/List.h"
  5. #include "utils/StringBuffer.h"
  6. #include "utils/Types.h"
  7. #include "utils/Utils.h"
  8. #include <unordered_map>
  9. template<typename K, typename V>
  10. struct HashMap final {
  11. class Node {
  12. friend HashMap;
  13. friend List<Node>;
  14. K key;
  15. public:
  16. V value;
  17. const K& getKey() const {
  18. return key;
  19. }
  20. private:
  21. int next;
  22. Node(const K& key, const V& value) : key(key), value(value), next(-1) {
  23. }
  24. Node(const K& key, V&& value)
  25. : key(key), value(std::move(value)), next(-1) {
  26. }
  27. template<typename... Args>
  28. Node(const K& key, Args&&... args)
  29. : key(key), value(std::forward<Args>(args)...), next(-1) {
  30. }
  31. };
  32. private:
  33. List<List<Node>> nodes;
  34. int elements;
  35. public:
  36. HashMap(int minCapacity = 8) : elements(0) {
  37. nodes.resize(1 << Utils::roundUpLog2(minCapacity));
  38. }
  39. template<typename... Args>
  40. bool tryEmplace(const K& key, Args&&... args) {
  41. rehash();
  42. Hash h = hash(key);
  43. V* v = searchList(key, h);
  44. if(v == nullptr) {
  45. nodes[h].add(key, std::forward<Args>(args)...);
  46. elements++;
  47. return false;
  48. }
  49. return true;
  50. }
  51. HashMap& add(const K& key, const V& value) {
  52. rehash();
  53. Hash h = hash(key);
  54. V* v = searchList(key, h);
  55. if(v == nullptr) {
  56. nodes[h].add(key, value);
  57. elements++;
  58. } else {
  59. *v = value;
  60. }
  61. return *this;
  62. }
  63. HashMap& add(const K& key, V&& value) {
  64. rehash();
  65. Hash h = hash(key);
  66. V* v = searchList(key, h);
  67. if(v == nullptr) {
  68. nodes[h].add(key, std::move(value));
  69. elements++;
  70. } else {
  71. *v = std::move(value);
  72. }
  73. return *this;
  74. }
  75. bool remove(const K& key) {
  76. List<Node>& list = nodes[hash(key)];
  77. for(int i = 0; i < list.getLength(); i++) {
  78. if(list[i].key == key) {
  79. list.remove(i);
  80. return true;
  81. }
  82. }
  83. return false;
  84. }
  85. const V* search(const K& key) const {
  86. return searchList(key, hash(key));
  87. }
  88. V* search(const K& key) {
  89. return searchList(key, hash(key));
  90. }
  91. bool contains(const K& key) const {
  92. return search(key) != nullptr;
  93. }
  94. HashMap& clear() {
  95. for(List<Node>& n : nodes) {
  96. n.clear();
  97. }
  98. elements = 0;
  99. return *this;
  100. }
  101. Node* begin() {
  102. return nodes.begin();
  103. }
  104. Node* end() {
  105. return nodes.end();
  106. }
  107. const Node* begin() const {
  108. return nodes.begin();
  109. }
  110. const Node* end() const {
  111. return nodes.end();
  112. }
  113. template<int L>
  114. void toString(StringBuffer<L>& s) const {
  115. s.append("[");
  116. bool c = false;
  117. for(const List<Node>& list : nodes) {
  118. for(const Node& n : list) {
  119. if(c) {
  120. s.append(", ");
  121. }
  122. s.append(n.key).append(" = ").append(n.value);
  123. c = true;
  124. }
  125. }
  126. s.append("]");
  127. }
  128. private:
  129. template<typename H>
  130. Hash hash(const H& key) const {
  131. return fullHash(key) & (nodes.getLength() - 1);
  132. }
  133. template<typename H>
  134. Hash fullHash(const H& key) const {
  135. return key.hashCode();
  136. }
  137. Hash fullHash(int key) const {
  138. return key;
  139. }
  140. void rehash() {
  141. if(elements < nodes.getLength()) {
  142. return;
  143. }
  144. HashMap<K, V> map(nodes.getLength() * 2);
  145. for(List<Node>& list : nodes) {
  146. for(Node& n : list) {
  147. map.tryEmplace(n.key, std::move(n.value));
  148. }
  149. }
  150. *this = std::move(map);
  151. }
  152. const V* searchList(const K& key, Hash h) const {
  153. for(const Node& n : nodes[h]) {
  154. if(n.key == key) {
  155. return &n.value;
  156. }
  157. }
  158. return nullptr;
  159. }
  160. V* searchList(const K& key, Hash h) {
  161. return const_cast<V*>(
  162. static_cast<const HashMap*>(this)->searchList(key, h));
  163. }
  164. };
  165. #endif