HashMap.h 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. #ifndef HASHMAP_H
  2. #define HASHMAP_H
  3. #include "utils/Array.h"
  4. #include "utils/Utils.h"
  5. #include "utils/List.h"
  6. #include "utils/StringBuffer.h"
  7. #include <iostream>
  8. template<typename K, typename V, int N_MIN>
  9. class HashMap final {
  10. static constexpr int CAPACITY = 1 << Utils::roundUpLog2(N_MIN);
  11. static constexpr int MASK = CAPACITY - 1;
  12. Array<int, CAPACITY> used;
  13. List<K, CAPACITY> keys;
  14. List<V, CAPACITY> values;
  15. enum SearchResult {
  16. FREE_INDEX_FOUND, KEY_FOUND, NOTHING_FOUND
  17. };
  18. struct Search {
  19. int index;
  20. SearchResult result;
  21. Search(int index, SearchResult result) : index(index), result(result) {
  22. }
  23. };
  24. Search searchIndex(const K& key) const {
  25. int base = hash(key);
  26. for(int i = 0; i < CAPACITY; i++) {
  27. int h = (base + i) & MASK;
  28. if(used[h] == -1) {
  29. return Search(h, FREE_INDEX_FOUND);
  30. } else if(keys[used[h]] == key) {
  31. return Search(h, KEY_FOUND);
  32. }
  33. }
  34. return Search(-1, NOTHING_FOUND);
  35. }
  36. template<typename H>
  37. static int hash(const H& key) {
  38. return key.hashCode();
  39. }
  40. static int hash(int key) {
  41. return key;
  42. }
  43. public:
  44. HashMap() : used(-1) {
  45. }
  46. HashMap(const HashMap& other) : used(other.used), keys(other.keys), values(other.values) {
  47. }
  48. HashMap& operator=(const HashMap& other) {
  49. if(&other != this) {
  50. used = other.used;
  51. keys = other.keys;
  52. values = other.values;
  53. }
  54. return *this;
  55. }
  56. HashMap(HashMap&& other) : used(other.used), keys(std::move(other.keys)), values(std::move(other.values)) {
  57. other.used.fill(-1);
  58. }
  59. HashMap& operator=(HashMap&& other) {
  60. if(&other != this) {
  61. used = std::move(other.used);
  62. keys = std::move(other.keys);
  63. values = std::move(other.values);
  64. other.used.fill(-1);
  65. }
  66. return *this;
  67. }
  68. template<typename... Args>
  69. bool tryEmplace(const K& key, Args&&... args) {
  70. Search s = searchIndex(key);
  71. if(s.result == FREE_INDEX_FOUND) {
  72. used[s.index] = keys.getLength();
  73. keys.add(key);
  74. values.add(std::forward<Args>(args)...);
  75. return false;
  76. }
  77. return true;
  78. }
  79. HashMap& add(const K& key, const V& value) {
  80. Search s = searchIndex(key);
  81. if(s.result == KEY_FOUND) {
  82. values[used[s.index]] = value;
  83. } else if(s.result == FREE_INDEX_FOUND) {
  84. used[s.index] = keys.getLength();
  85. keys.add(key);
  86. values.add(value);
  87. }
  88. return *this;
  89. }
  90. HashMap& add(const K& key, const V&& value) {
  91. Search s = searchIndex(key);
  92. if(s.result == KEY_FOUND) {
  93. values[used[s.index]] = std::move(value);
  94. } else if(s.result == FREE_INDEX_FOUND) {
  95. used[s.index] = keys.getLength();
  96. keys.add(key);
  97. values.add(std::move(value));
  98. }
  99. return *this;
  100. }
  101. const V& search(const K& key, const V& notFound) const {
  102. Search s = searchIndex(key);
  103. return s.result == KEY_FOUND ? values[used[s.index]] : notFound;
  104. }
  105. V& search(const K& key, V& notFound) {
  106. Search s = searchIndex(key);
  107. return s.result == KEY_FOUND ? values[used[s.index]] : notFound;
  108. }
  109. bool contains(const K& key) const {
  110. return searchIndex(key).result == KEY_FOUND;
  111. }
  112. HashMap& clear() {
  113. keys.clear();
  114. values.clear();
  115. used.fill(-1);
  116. return *this;
  117. }
  118. template<int L>
  119. void toString(StringBuffer<L>& s) const {
  120. s.append("[");
  121. bool c = false;
  122. for(int i = 0; i < CAPACITY; i++) {
  123. if(used[i] == -1) {
  124. continue;
  125. } else if(c) {
  126. s.append(", ");
  127. }
  128. s.append(keys[used[i]]).append(" = ").append(values[used[i]]);
  129. c = true;
  130. }
  131. s.append("]");
  132. }
  133. };
  134. #endif