tree-set-typed 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (273) hide show
  1. package/.eslintrc.js +61 -0
  2. package/.prettierignore +6 -0
  3. package/.prettierrc.js +16 -0
  4. package/LICENSE +21 -0
  5. package/README.md +482 -0
  6. package/coverage/clover.xml +13 -0
  7. package/coverage/coverage-final.json +96 -0
  8. package/coverage/coverage-summary.json +60 -0
  9. package/coverage/lcov-report/base.css +403 -0
  10. package/coverage/lcov-report/block-navigation.js +87 -0
  11. package/coverage/lcov-report/favicon.png +0 -0
  12. package/coverage/lcov-report/index.html +119 -0
  13. package/coverage/lcov-report/index.ts.html +109 -0
  14. package/coverage/lcov-report/prettify.css +1 -0
  15. package/coverage/lcov-report/prettify.js +2 -0
  16. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  17. package/coverage/lcov-report/sorter.js +206 -0
  18. package/coverage/lcov.info +14 -0
  19. package/dist/cjs/index.cjs +12 -0
  20. package/dist/cjs/index.cjs.map +1 -0
  21. package/dist/cjs-legacy/index.cjs +12 -0
  22. package/dist/cjs-legacy/index.cjs.map +1 -0
  23. package/dist/esm/index.mjs +3 -0
  24. package/dist/esm/index.mjs.map +1 -0
  25. package/dist/esm-legacy/index.mjs +3 -0
  26. package/dist/esm-legacy/index.mjs.map +1 -0
  27. package/dist/types/common/index.d.ts +12 -0
  28. package/dist/types/constants/index.d.ts +4 -0
  29. package/dist/types/data-structures/base/index.d.ts +2 -0
  30. package/dist/types/data-structures/base/iterable-element-base.d.ts +219 -0
  31. package/dist/types/data-structures/base/iterable-entry-base.d.ts +150 -0
  32. package/dist/types/data-structures/base/linear-base.d.ts +335 -0
  33. package/dist/types/data-structures/binary-tree/avl-tree-counter.d.ts +236 -0
  34. package/dist/types/data-structures/binary-tree/avl-tree-multi-map.d.ts +197 -0
  35. package/dist/types/data-structures/binary-tree/avl-tree.d.ts +440 -0
  36. package/dist/types/data-structures/binary-tree/binary-indexed-tree.d.ts +174 -0
  37. package/dist/types/data-structures/binary-tree/binary-tree.d.ts +807 -0
  38. package/dist/types/data-structures/binary-tree/bst.d.ts +645 -0
  39. package/dist/types/data-structures/binary-tree/index.d.ts +10 -0
  40. package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +312 -0
  41. package/dist/types/data-structures/binary-tree/segment-tree.d.ts +160 -0
  42. package/dist/types/data-structures/binary-tree/tree-counter.d.ts +243 -0
  43. package/dist/types/data-structures/binary-tree/tree-multi-map.d.ts +333 -0
  44. package/dist/types/data-structures/graph/abstract-graph.d.ts +340 -0
  45. package/dist/types/data-structures/graph/directed-graph.d.ts +332 -0
  46. package/dist/types/data-structures/graph/index.d.ts +4 -0
  47. package/dist/types/data-structures/graph/map-graph.d.ts +78 -0
  48. package/dist/types/data-structures/graph/undirected-graph.d.ts +347 -0
  49. package/dist/types/data-structures/hash/hash-map.d.ts +428 -0
  50. package/dist/types/data-structures/hash/index.d.ts +1 -0
  51. package/dist/types/data-structures/heap/heap.d.ts +552 -0
  52. package/dist/types/data-structures/heap/index.d.ts +3 -0
  53. package/dist/types/data-structures/heap/max-heap.d.ts +32 -0
  54. package/dist/types/data-structures/heap/min-heap.d.ts +33 -0
  55. package/dist/types/data-structures/index.d.ts +12 -0
  56. package/dist/types/data-structures/linked-list/doubly-linked-list.d.ts +437 -0
  57. package/dist/types/data-structures/linked-list/index.d.ts +3 -0
  58. package/dist/types/data-structures/linked-list/singly-linked-list.d.ts +567 -0
  59. package/dist/types/data-structures/linked-list/skip-linked-list.d.ts +27 -0
  60. package/dist/types/data-structures/matrix/index.d.ts +2 -0
  61. package/dist/types/data-structures/matrix/matrix.d.ts +168 -0
  62. package/dist/types/data-structures/matrix/navigator.d.ts +55 -0
  63. package/dist/types/data-structures/priority-queue/index.d.ts +3 -0
  64. package/dist/types/data-structures/priority-queue/max-priority-queue.d.ts +27 -0
  65. package/dist/types/data-structures/priority-queue/min-priority-queue.d.ts +26 -0
  66. package/dist/types/data-structures/priority-queue/priority-queue.d.ts +15 -0
  67. package/dist/types/data-structures/queue/deque.d.ts +459 -0
  68. package/dist/types/data-structures/queue/index.d.ts +2 -0
  69. package/dist/types/data-structures/queue/queue.d.ts +364 -0
  70. package/dist/types/data-structures/stack/index.d.ts +1 -0
  71. package/dist/types/data-structures/stack/stack.d.ts +324 -0
  72. package/dist/types/data-structures/tree/index.d.ts +1 -0
  73. package/dist/types/data-structures/tree/tree.d.ts +62 -0
  74. package/dist/types/data-structures/trie/index.d.ts +1 -0
  75. package/dist/types/data-structures/trie/trie.d.ts +412 -0
  76. package/dist/types/index.d.ts +23 -0
  77. package/dist/types/interfaces/binary-tree.d.ts +60 -0
  78. package/dist/types/interfaces/doubly-linked-list.d.ts +1 -0
  79. package/dist/types/interfaces/graph.d.ts +21 -0
  80. package/dist/types/interfaces/heap.d.ts +1 -0
  81. package/dist/types/interfaces/index.d.ts +8 -0
  82. package/dist/types/interfaces/navigator.d.ts +1 -0
  83. package/dist/types/interfaces/priority-queue.d.ts +1 -0
  84. package/dist/types/interfaces/segment-tree.d.ts +1 -0
  85. package/dist/types/interfaces/singly-linked-list.d.ts +1 -0
  86. package/dist/types/types/common.d.ts +15 -0
  87. package/dist/types/types/data-structures/base/base.d.ts +13 -0
  88. package/dist/types/types/data-structures/base/index.d.ts +1 -0
  89. package/dist/types/types/data-structures/binary-tree/avl-tree-counter.d.ts +2 -0
  90. package/dist/types/types/data-structures/binary-tree/avl-tree-multi-map.d.ts +2 -0
  91. package/dist/types/types/data-structures/binary-tree/avl-tree.d.ts +2 -0
  92. package/dist/types/types/data-structures/binary-tree/binary-indexed-tree.d.ts +1 -0
  93. package/dist/types/types/data-structures/binary-tree/binary-tree.d.ts +29 -0
  94. package/dist/types/types/data-structures/binary-tree/bst.d.ts +12 -0
  95. package/dist/types/types/data-structures/binary-tree/index.d.ts +9 -0
  96. package/dist/types/types/data-structures/binary-tree/red-black-tree.d.ts +3 -0
  97. package/dist/types/types/data-structures/binary-tree/segment-tree.d.ts +1 -0
  98. package/dist/types/types/data-structures/binary-tree/tree-counter.d.ts +2 -0
  99. package/dist/types/types/data-structures/binary-tree/tree-multi-map.d.ts +2 -0
  100. package/dist/types/types/data-structures/graph/abstract-graph.d.ts +14 -0
  101. package/dist/types/types/data-structures/graph/directed-graph.d.ts +1 -0
  102. package/dist/types/types/data-structures/graph/index.d.ts +3 -0
  103. package/dist/types/types/data-structures/graph/map-graph.d.ts +1 -0
  104. package/dist/types/types/data-structures/graph/undirected-graph.d.ts +1 -0
  105. package/dist/types/types/data-structures/hash/hash-map.d.ts +19 -0
  106. package/dist/types/types/data-structures/hash/index.d.ts +2 -0
  107. package/dist/types/types/data-structures/heap/heap.d.ts +5 -0
  108. package/dist/types/types/data-structures/heap/index.d.ts +1 -0
  109. package/dist/types/types/data-structures/heap/max-heap.d.ts +1 -0
  110. package/dist/types/types/data-structures/heap/min-heap.d.ts +1 -0
  111. package/dist/types/types/data-structures/index.d.ts +12 -0
  112. package/dist/types/types/data-structures/linked-list/doubly-linked-list.d.ts +2 -0
  113. package/dist/types/types/data-structures/linked-list/index.d.ts +3 -0
  114. package/dist/types/types/data-structures/linked-list/singly-linked-list.d.ts +2 -0
  115. package/dist/types/types/data-structures/linked-list/skip-linked-list.d.ts +4 -0
  116. package/dist/types/types/data-structures/matrix/index.d.ts +2 -0
  117. package/dist/types/types/data-structures/matrix/matrix.d.ts +7 -0
  118. package/dist/types/types/data-structures/matrix/navigator.d.ts +14 -0
  119. package/dist/types/types/data-structures/priority-queue/index.d.ts +3 -0
  120. package/dist/types/types/data-structures/priority-queue/max-priority-queue.d.ts +1 -0
  121. package/dist/types/types/data-structures/priority-queue/min-priority-queue.d.ts +1 -0
  122. package/dist/types/types/data-structures/priority-queue/priority-queue.d.ts +2 -0
  123. package/dist/types/types/data-structures/queue/deque.d.ts +4 -0
  124. package/dist/types/types/data-structures/queue/index.d.ts +2 -0
  125. package/dist/types/types/data-structures/queue/queue.d.ts +4 -0
  126. package/dist/types/types/data-structures/stack/index.d.ts +1 -0
  127. package/dist/types/types/data-structures/stack/stack.d.ts +2 -0
  128. package/dist/types/types/data-structures/tree/index.d.ts +1 -0
  129. package/dist/types/types/data-structures/tree/tree.d.ts +1 -0
  130. package/dist/types/types/data-structures/trie/index.d.ts +1 -0
  131. package/dist/types/types/data-structures/trie/trie.d.ts +4 -0
  132. package/dist/types/types/index.d.ts +3 -0
  133. package/dist/types/types/utils/index.d.ts +2 -0
  134. package/dist/types/types/utils/utils.d.ts +22 -0
  135. package/dist/types/types/utils/validate-type.d.ts +19 -0
  136. package/dist/types/utils/index.d.ts +2 -0
  137. package/dist/types/utils/number.d.ts +14 -0
  138. package/dist/types/utils/utils.d.ts +209 -0
  139. package/dist/umd/red-black-tree-typed.js +14578 -0
  140. package/dist/umd/red-black-tree-typed.js.map +1 -0
  141. package/dist/umd/red-black-tree-typed.min.js +44 -0
  142. package/dist/umd/red-black-tree-typed.min.js.map +1 -0
  143. package/docs/.nojekyll +1 -0
  144. package/docs/assets/highlight.css +92 -0
  145. package/docs/assets/main.js +59 -0
  146. package/docs/assets/navigation.js +1 -0
  147. package/docs/assets/search.js +1 -0
  148. package/docs/assets/style.css +1383 -0
  149. package/docs/classes/AVLTree.html +2046 -0
  150. package/docs/classes/AVLTreeNode.html +263 -0
  151. package/docs/index.html +523 -0
  152. package/docs/modules.html +45 -0
  153. package/jest.config.js +8 -0
  154. package/package.json +113 -0
  155. package/src/common/index.ts +23 -0
  156. package/src/constants/index.ts +4 -0
  157. package/src/data-structures/base/index.ts +2 -0
  158. package/src/data-structures/base/iterable-element-base.ts +352 -0
  159. package/src/data-structures/base/iterable-entry-base.ts +246 -0
  160. package/src/data-structures/base/linear-base.ts +643 -0
  161. package/src/data-structures/binary-tree/avl-tree-counter.ts +539 -0
  162. package/src/data-structures/binary-tree/avl-tree-multi-map.ts +438 -0
  163. package/src/data-structures/binary-tree/avl-tree.ts +840 -0
  164. package/src/data-structures/binary-tree/binary-indexed-tree.ts +331 -0
  165. package/src/data-structures/binary-tree/binary-tree.ts +2492 -0
  166. package/src/data-structures/binary-tree/bst.ts +2024 -0
  167. package/src/data-structures/binary-tree/index.ts +10 -0
  168. package/src/data-structures/binary-tree/red-black-tree.ts +767 -0
  169. package/src/data-structures/binary-tree/segment-tree.ts +324 -0
  170. package/src/data-structures/binary-tree/tree-counter.ts +575 -0
  171. package/src/data-structures/binary-tree/tree-multi-map.ts +549 -0
  172. package/src/data-structures/graph/abstract-graph.ts +1081 -0
  173. package/src/data-structures/graph/directed-graph.ts +715 -0
  174. package/src/data-structures/graph/index.ts +4 -0
  175. package/src/data-structures/graph/map-graph.ts +132 -0
  176. package/src/data-structures/graph/undirected-graph.ts +626 -0
  177. package/src/data-structures/hash/hash-map.ts +813 -0
  178. package/src/data-structures/hash/index.ts +1 -0
  179. package/src/data-structures/heap/heap.ts +1020 -0
  180. package/src/data-structures/heap/index.ts +3 -0
  181. package/src/data-structures/heap/max-heap.ts +47 -0
  182. package/src/data-structures/heap/min-heap.ts +36 -0
  183. package/src/data-structures/index.ts +12 -0
  184. package/src/data-structures/linked-list/doubly-linked-list.ts +876 -0
  185. package/src/data-structures/linked-list/index.ts +3 -0
  186. package/src/data-structures/linked-list/singly-linked-list.ts +1050 -0
  187. package/src/data-structures/linked-list/skip-linked-list.ts +173 -0
  188. package/src/data-structures/matrix/index.ts +2 -0
  189. package/src/data-structures/matrix/matrix.ts +491 -0
  190. package/src/data-structures/matrix/navigator.ts +124 -0
  191. package/src/data-structures/priority-queue/index.ts +3 -0
  192. package/src/data-structures/priority-queue/max-priority-queue.ts +42 -0
  193. package/src/data-structures/priority-queue/min-priority-queue.ts +29 -0
  194. package/src/data-structures/priority-queue/priority-queue.ts +19 -0
  195. package/src/data-structures/queue/deque.ts +1001 -0
  196. package/src/data-structures/queue/index.ts +2 -0
  197. package/src/data-structures/queue/queue.ts +592 -0
  198. package/src/data-structures/stack/index.ts +1 -0
  199. package/src/data-structures/stack/stack.ts +469 -0
  200. package/src/data-structures/tree/index.ts +1 -0
  201. package/src/data-structures/tree/tree.ts +115 -0
  202. package/src/data-structures/trie/index.ts +1 -0
  203. package/src/data-structures/trie/trie.ts +756 -0
  204. package/src/index.ts +24 -0
  205. package/src/interfaces/binary-tree.ts +252 -0
  206. package/src/interfaces/doubly-linked-list.ts +1 -0
  207. package/src/interfaces/graph.ts +44 -0
  208. package/src/interfaces/heap.ts +1 -0
  209. package/src/interfaces/index.ts +8 -0
  210. package/src/interfaces/navigator.ts +1 -0
  211. package/src/interfaces/priority-queue.ts +1 -0
  212. package/src/interfaces/segment-tree.ts +1 -0
  213. package/src/interfaces/singly-linked-list.ts +1 -0
  214. package/src/types/common.ts +25 -0
  215. package/src/types/data-structures/base/base.ts +34 -0
  216. package/src/types/data-structures/base/index.ts +1 -0
  217. package/src/types/data-structures/binary-tree/avl-tree-counter.ts +3 -0
  218. package/src/types/data-structures/binary-tree/avl-tree-multi-map.ts +3 -0
  219. package/src/types/data-structures/binary-tree/avl-tree.ts +3 -0
  220. package/src/types/data-structures/binary-tree/binary-indexed-tree.ts +1 -0
  221. package/src/types/data-structures/binary-tree/binary-tree.ts +31 -0
  222. package/src/types/data-structures/binary-tree/bst.ts +19 -0
  223. package/src/types/data-structures/binary-tree/index.ts +9 -0
  224. package/src/types/data-structures/binary-tree/red-black-tree.ts +5 -0
  225. package/src/types/data-structures/binary-tree/segment-tree.ts +1 -0
  226. package/src/types/data-structures/binary-tree/tree-counter.ts +3 -0
  227. package/src/types/data-structures/binary-tree/tree-multi-map.ts +3 -0
  228. package/src/types/data-structures/graph/abstract-graph.ts +18 -0
  229. package/src/types/data-structures/graph/directed-graph.ts +2 -0
  230. package/src/types/data-structures/graph/index.ts +3 -0
  231. package/src/types/data-structures/graph/map-graph.ts +1 -0
  232. package/src/types/data-structures/graph/undirected-graph.ts +1 -0
  233. package/src/types/data-structures/hash/hash-map.ts +19 -0
  234. package/src/types/data-structures/hash/index.ts +3 -0
  235. package/src/types/data-structures/heap/heap.ts +6 -0
  236. package/src/types/data-structures/heap/index.ts +1 -0
  237. package/src/types/data-structures/heap/max-heap.ts +1 -0
  238. package/src/types/data-structures/heap/min-heap.ts +1 -0
  239. package/src/types/data-structures/index.ts +12 -0
  240. package/src/types/data-structures/linked-list/doubly-linked-list.ts +3 -0
  241. package/src/types/data-structures/linked-list/index.ts +3 -0
  242. package/src/types/data-structures/linked-list/singly-linked-list.ts +3 -0
  243. package/src/types/data-structures/linked-list/skip-linked-list.ts +1 -0
  244. package/src/types/data-structures/matrix/index.ts +2 -0
  245. package/src/types/data-structures/matrix/matrix.ts +7 -0
  246. package/src/types/data-structures/matrix/navigator.ts +14 -0
  247. package/src/types/data-structures/priority-queue/index.ts +3 -0
  248. package/src/types/data-structures/priority-queue/max-priority-queue.ts +1 -0
  249. package/src/types/data-structures/priority-queue/min-priority-queue.ts +1 -0
  250. package/src/types/data-structures/priority-queue/priority-queue.ts +3 -0
  251. package/src/types/data-structures/queue/deque.ts +5 -0
  252. package/src/types/data-structures/queue/index.ts +2 -0
  253. package/src/types/data-structures/queue/queue.ts +5 -0
  254. package/src/types/data-structures/stack/index.ts +1 -0
  255. package/src/types/data-structures/stack/stack.ts +3 -0
  256. package/src/types/data-structures/tree/index.ts +1 -0
  257. package/src/types/data-structures/tree/tree.ts +1 -0
  258. package/src/types/data-structures/trie/index.ts +1 -0
  259. package/src/types/data-structures/trie/trie.ts +3 -0
  260. package/src/types/index.ts +3 -0
  261. package/src/types/utils/index.ts +2 -0
  262. package/src/types/utils/utils.ts +33 -0
  263. package/src/types/utils/validate-type.ts +35 -0
  264. package/src/utils/index.ts +2 -0
  265. package/src/utils/number.ts +22 -0
  266. package/src/utils/utils.ts +350 -0
  267. package/test/index.test.ts +111 -0
  268. package/tsconfig.base.json +23 -0
  269. package/tsconfig.json +12 -0
  270. package/tsconfig.test.json +8 -0
  271. package/tsconfig.types.json +15 -0
  272. package/tsup.config.js +28 -0
  273. package/tsup.node.config.js +71 -0
@@ -0,0 +1,813 @@
1
+ /**
2
+ * data-structure-typed
3
+ *
4
+ * @author Pablo Zeng
5
+ * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>
6
+ * @license MIT License
7
+ */
8
+
9
+ import type {
10
+ EntryCallback,
11
+ HashMapLinkedNode,
12
+ HashMapOptions,
13
+ HashMapStoreItem,
14
+ LinkedHashMapOptions
15
+ } from '../../types';
16
+ import { IterableEntryBase } from '../base';
17
+ import { isWeakKey, rangeCheck } from '../../utils';
18
+
19
+ /**
20
+ * Hash-based map. Supports object keys and custom hashing; offers O(1) average set/get/has.
21
+ * @remarks Time O(1), Space O(1)
22
+ * @template K
23
+ * @template V
24
+ * @template R
25
+ * 1. Key-Value Pair Storage: HashMap stores key-value pairs. Each key map to a value.
26
+ * 2. Fast Lookup: It's used when you need to quickly find, insert, or delete entries based on a key.
27
+ * 3. Unique Keys: Keys are unique.
28
+ * If you try to insert another entry with the same key, the new one will replace the old entry.
29
+ * 4. Unordered Collection: HashMap does not guarantee the order of entries, and the order may change over time.
30
+ * @example
31
+ * // should maintain insertion order
32
+ * const linkedHashMap = new LinkedHashMap<number, string>();
33
+ * linkedHashMap.set(1, 'A');
34
+ * linkedHashMap.set(2, 'B');
35
+ * linkedHashMap.set(3, 'C');
36
+ *
37
+ * const result = Array.from(linkedHashMap);
38
+ * console.log(result); // [
39
+ * // [1, 'A'],
40
+ * // [2, 'B'],
41
+ * // [3, 'C']
42
+ * // ];
43
+ * @example
44
+ * // basic HashMap creation and set operation
45
+ * // Create a simple HashMap with key-value pairs
46
+ * const map = new HashMap<number, string>([
47
+ * [1, 'one'],
48
+ * [2, 'two'],
49
+ * [3, 'three']
50
+ * ]);
51
+ *
52
+ * // Verify size
53
+ * console.log(map.size); // 3;
54
+ *
55
+ * // Set a new key-value pair
56
+ * map.set(4, 'four');
57
+ * console.log(map.size); // 4;
58
+ *
59
+ * // Verify entries
60
+ * console.log([...map.entries()]); // length: 4;
61
+ * @example
62
+ * // HashMap get and has operations
63
+ * const map = new HashMap<string, number>([
64
+ * ['apple', 1],
65
+ * ['banana', 2],
66
+ * ['cherry', 3]
67
+ * ]);
68
+ *
69
+ * // Check if key exists
70
+ * console.log(map.has('apple')); // true;
71
+ * console.log(map.has('date')); // false;
72
+ *
73
+ * // Get value by key
74
+ * console.log(map.get('banana')); // 2;
75
+ * console.log(map.get('grape')); // undefined;
76
+ *
77
+ * // Get all keys and values
78
+ * const keys = [...map.keys()];
79
+ * const values = [...map.values()];
80
+ * console.log(keys); // contains 'apple';
81
+ * console.log(values); // contains 3;
82
+ * @example
83
+ * // HashMap iteration and filter operations
84
+ * const map = new HashMap<number, string>([
85
+ * [1, 'Alice'],
86
+ * [2, 'Bob'],
87
+ * [3, 'Charlie'],
88
+ * [4, 'Diana'],
89
+ * [5, 'Eve']
90
+ * ]);
91
+ *
92
+ * // Iterate through entries
93
+ * const entries: [number, string][] = [];
94
+ * for (const [key, value] of map) {
95
+ * entries.push([key, value]);
96
+ * }
97
+ * console.log(entries); // length: 5;
98
+ *
99
+ * // Filter operation (for iteration with collection methods)
100
+ * const filtered = [...map].filter(([key]) => key > 2);
101
+ * console.log(filtered.length); // 3;
102
+ *
103
+ * // Map operation
104
+ * const values = [...map.values()].map(v => v.length);
105
+ * console.log(values); // contains 3; // 'Bob', 'Eve'
106
+ * console.log(values); // contains 7;
107
+ * @example
108
+ * // HashMap for user session caching O(1) performance
109
+ * interface UserSession {
110
+ * userId: number;
111
+ * username: string;
112
+ * loginTime: number;
113
+ * lastActivity: number;
114
+ * }
115
+ *
116
+ * // HashMap provides O(1) average-case performance for set/get/delete
117
+ * // Perfect for session management with fast lookups
118
+ * const sessionCache = new HashMap<string, UserSession>();
119
+ *
120
+ * // Simulate user sessions
121
+ * const sessions: [string, UserSession][] = [
122
+ * ['session_001', { userId: 1, username: 'alice', loginTime: 1000, lastActivity: 1050 }],
123
+ * ['session_002', { userId: 2, username: 'bob', loginTime: 1100, lastActivity: 1150 }],
124
+ * ['session_003', { userId: 3, username: 'charlie', loginTime: 1200, lastActivity: 1250 }]
125
+ * ];
126
+ *
127
+ * // Store sessions with O(1) insertion
128
+ * for (const [token, session] of sessions) {
129
+ * sessionCache.set(token, session);
130
+ * }
131
+ *
132
+ * console.log(sessionCache.size); // 3;
133
+ *
134
+ * // Retrieve session with O(1) lookup
135
+ * const userSession = sessionCache.get('session_001');
136
+ * console.log(userSession?.username); // 'alice';
137
+ * console.log(userSession?.userId); // 1;
138
+ *
139
+ * // Update session with O(1) operation
140
+ * if (userSession) {
141
+ * userSession.lastActivity = 2000;
142
+ * sessionCache.set('session_001', userSession);
143
+ * }
144
+ *
145
+ * // Check updated value
146
+ * const updated = sessionCache.get('session_001');
147
+ * console.log(updated?.lastActivity); // 2000;
148
+ *
149
+ * // Cleanup: delete expired sessions
150
+ * sessionCache.delete('session_002');
151
+ * console.log(sessionCache.has('session_002')); // false;
152
+ *
153
+ * // Verify remaining sessions
154
+ * console.log(sessionCache.size); // 2;
155
+ *
156
+ * // Get all active sessions
157
+ * const activeCount = [...sessionCache.values()].length;
158
+ * console.log(activeCount); // 2;
159
+ */
160
+ export class HashMap<K = any, V = any, R = [K, V]> extends IterableEntryBase<K, V> {
161
+ /**
162
+ * Create a HashMap and optionally bulk-insert entries.
163
+ * @remarks Time O(N), Space O(N)
164
+ * @param [entryOrRawElements] - Iterable of entries or raw elements to insert.
165
+ * @param [options] - Options: hash function and optional record-to-entry converter.
166
+ * @returns New HashMap instance.
167
+ */
168
+ constructor(entryOrRawElements: Iterable<R | [K, V]> = [], options?: HashMapOptions<K, V, R>) {
169
+ super();
170
+ if (options) {
171
+ const { hashFn, toEntryFn } = options;
172
+ if (hashFn) this._hashFn = hashFn;
173
+ if (toEntryFn) this._toEntryFn = toEntryFn;
174
+ }
175
+ if (entryOrRawElements) this.setMany(entryOrRawElements);
176
+ }
177
+
178
+ protected _store: { [key: string]: HashMapStoreItem<K, V> } = {};
179
+
180
+ /**
181
+ * Get the internal store for non-object keys.
182
+ * @remarks Time O(1), Space O(1)
183
+ * @returns Internal record of string→{key,value}.
184
+ */
185
+ get store(): { [p: string]: HashMapStoreItem<K, V> } {
186
+ return this._store;
187
+ }
188
+
189
+ protected _objMap: Map<object, V> = new Map();
190
+
191
+ /**
192
+ * Get the internal Map used for object/function keys.
193
+ * @remarks Time O(1), Space O(1)
194
+ * @returns Map of object→value.
195
+ */
196
+ get objMap(): Map<object, V> {
197
+ return this._objMap;
198
+ }
199
+
200
+ protected _toEntryFn?: (rawElement: R) => [K, V];
201
+
202
+ /**
203
+ * Get the raw→entry converter function if present.
204
+ * @remarks Time O(1), Space O(1)
205
+ * @returns Converter function or undefined.
206
+ */
207
+ get toEntryFn() {
208
+ return this._toEntryFn;
209
+ }
210
+
211
+ protected _size = 0;
212
+
213
+ /**
214
+ * Get the number of distinct keys stored.
215
+ * @remarks Time O(1), Space O(1)
216
+ * @returns Current size.
217
+ */
218
+ get size(): number {
219
+ return this._size;
220
+ }
221
+
222
+ protected _hashFn: (key: K) => string = (key: K) => String(key);
223
+
224
+ /**
225
+ * Get the current hash function for non-object keys.
226
+ * @remarks Time O(1), Space O(1)
227
+ * @returns Hash function.
228
+ */
229
+ get hashFn() {
230
+ return this._hashFn;
231
+ }
232
+
233
+ /**
234
+ * Check whether the map is empty.
235
+ * @remarks Time O(1), Space O(1)
236
+ * @returns True if size is 0.
237
+ */
238
+ isEmpty(): boolean {
239
+ return this._size === 0;
240
+ }
241
+
242
+ /**
243
+ * Remove all entries and reset counters.
244
+ * @remarks Time O(N), Space O(1)
245
+ * @returns void
246
+ */
247
+ clear(): void {
248
+ this._store = {};
249
+ this._objMap.clear();
250
+ this._size = 0;
251
+ }
252
+
253
+ /**
254
+ * Type guard: check if a raw value is a [key, value] entry.
255
+ * @remarks Time O(1), Space O(1)
256
+ * @returns True if the value is a 2-tuple.
257
+ */
258
+ isEntry(rawElement: any): rawElement is [K, V] {
259
+ return Array.isArray(rawElement) && rawElement.length === 2;
260
+ }
261
+
262
+ /**
263
+ * Insert or replace a single entry.
264
+ * @remarks Time O(1), Space O(1)
265
+ * @param key - Key.
266
+ * @param value - Value.
267
+ * @returns True when the operation succeeds.
268
+ */
269
+ set(key: K, value: V): boolean {
270
+ if (this._isObjKey(key)) {
271
+ if (!this.objMap.has(key)) this._size++;
272
+ this.objMap.set(key, value);
273
+ } else {
274
+ const strKey = this._getNoObjKey(key);
275
+ if (this.store[strKey] === undefined) this._size++;
276
+ this._store[strKey] = { key, value };
277
+ }
278
+ return true;
279
+ }
280
+
281
+ /**
282
+ * Insert many entries from an iterable.
283
+ * @remarks Time O(N), Space O(N)
284
+ * @param entryOrRawElements - Iterable of entries or raw elements to insert.
285
+ * @returns Array of per-entry results.
286
+ */
287
+ setMany(entryOrRawElements: Iterable<R | [K, V]>): boolean[] {
288
+ const results: boolean[] = [];
289
+ for (const rawEle of entryOrRawElements) {
290
+ let key: K | undefined, value: V | undefined;
291
+ if (this.isEntry(rawEle)) [key, value] = rawEle;
292
+ else if (this._toEntryFn) [key, value] = this._toEntryFn(rawEle);
293
+ if (key !== undefined && value !== undefined) results.push(this.set(key, value));
294
+ }
295
+ return results;
296
+ }
297
+
298
+ /**
299
+ * Get the value for a key.
300
+ * @remarks Time O(1), Space O(1)
301
+ * @param key - Key to look up.
302
+ * @returns Value or undefined.
303
+ */
304
+ override get(key: K): V | undefined {
305
+ if (this._isObjKey(key)) return this.objMap.get(key);
306
+ const strKey = this._getNoObjKey(key);
307
+ return this._store[strKey]?.value;
308
+ }
309
+
310
+ /**
311
+ * Check if a key exists.
312
+ * @remarks Time O(1), Space O(1)
313
+ * @param key - Key to test.
314
+ * @returns True if present.
315
+ */
316
+ override has(key: K): boolean {
317
+ if (this._isObjKey(key)) return this.objMap.has(key);
318
+ const strKey = this._getNoObjKey(key);
319
+ return strKey in this.store;
320
+ }
321
+
322
+ /**
323
+ * Delete an entry by key.
324
+ * @remarks Time O(1), Space O(1)
325
+ * @param key - Key to delete.
326
+ * @returns True if the key was found and removed.
327
+ */
328
+ delete(key: K): boolean {
329
+ if (this._isObjKey(key)) {
330
+ if (this.objMap.has(key)) this._size--;
331
+ return this.objMap.delete(key);
332
+ }
333
+ const strKey = this._getNoObjKey(key);
334
+ if (strKey in this.store) {
335
+ delete this.store[strKey];
336
+ this._size--;
337
+ return true;
338
+ }
339
+ return false;
340
+ }
341
+
342
+ /**
343
+ * Replace the hash function and rehash the non-object store.
344
+ * @remarks Time O(N), Space O(N)
345
+ * @param fn - New hash function for non-object keys.
346
+ * @returns This map instance.
347
+ */
348
+ setHashFn(fn: (key: K) => string): this {
349
+ if (this._hashFn === fn) return this;
350
+ this._hashFn = fn;
351
+ this._rehashNoObj();
352
+ return this;
353
+ }
354
+
355
+ /**
356
+ * Deep clone this map, preserving hashing behavior.
357
+ * @remarks Time O(N), Space O(N)
358
+ * @returns A new map with the same content.
359
+ */
360
+ clone(): this {
361
+ const opts = { hashFn: this._hashFn, toEntryFn: this._toEntryFn };
362
+ return this._createLike<[K, V], [K, V], [K, V]>(this, opts);
363
+ }
364
+
365
+ /**
366
+ * Map values to a new map with the same keys.
367
+ * @remarks Time O(N), Space O(N)
368
+ * @template VM
369
+ * @param callbackfn - Mapping function (key, value, index, map) → newValue.
370
+ * @param [thisArg] - Value for `this` inside the callback.
371
+ * @returns A new map with transformed values.
372
+ */
373
+ map<VM>(callbackfn: EntryCallback<K, V, VM>, thisArg?: any): any {
374
+ const out = this._createLike<K, VM, [K, VM]>();
375
+ let index = 0;
376
+ for (const [key, value] of this) out.set(key, callbackfn.call(thisArg, value, key, index++, this));
377
+ return out;
378
+ }
379
+
380
+ /**
381
+ * Filter entries into a new map.
382
+ * @remarks Time O(N), Space O(N)
383
+ * @param predicate - Predicate (key, value, index, map) → boolean.
384
+ * @param [thisArg] - Value for `this` inside the predicate.
385
+ * @returns A new map containing entries that satisfied the predicate.
386
+ */
387
+
388
+ filter(predicate: EntryCallback<K, V, boolean>, thisArg?: any): any {
389
+ const out = this._createLike<K, V, [K, V]>();
390
+ let index = 0;
391
+ for (const [key, value] of this) if (predicate.call(thisArg, value, key, index++, this)) out.set(key, value);
392
+ return out;
393
+ }
394
+
395
+ /**
396
+ * (Protected) Create a like-kind instance and seed it from an iterable.
397
+ * @remarks Time O(N), Space O(N)
398
+ * @template TK
399
+ * @template TV
400
+ * @template TR
401
+ * @param [entries] - Iterable used to seed the new map.
402
+ * @param [options] - Options forwarded to the constructor.
403
+ * @returns A like-kind map instance.
404
+ */
405
+ protected _createLike<TK = K, TV = V, TR = [TK, TV]>(entries: Iterable<[TK, TV] | TR> = [], options?: any): any {
406
+ const Ctor = this.constructor as new (e?: Iterable<[TK, TV] | TR>, o?: any) => any;
407
+ return new Ctor(entries, options);
408
+ }
409
+
410
+ protected _rehashNoObj(): void {
411
+ const fresh: Record<string, HashMapStoreItem<K, V>> = {};
412
+ for (const { key, value } of Object.values(this._store)) {
413
+ const sk = this._getNoObjKey(key);
414
+ fresh[sk] = { key, value };
415
+ }
416
+ this._store = fresh;
417
+ }
418
+
419
+ protected *_getIterator(): IterableIterator<[K, V]> {
420
+ for (const node of Object.values(this.store)) yield [node.key, node.value] as [K, V];
421
+ for (const node of this.objMap) yield node as [K, V];
422
+ }
423
+
424
+ protected _isObjKey(key: any): key is object | ((...args: any[]) => any) {
425
+ const keyType = typeof key;
426
+ return (keyType === 'object' || keyType === 'function') && key !== null;
427
+ }
428
+
429
+ protected _getNoObjKey(key: K): string {
430
+ const keyType = typeof key;
431
+
432
+ let strKey: string;
433
+ if (keyType !== 'string' && keyType !== 'number' && keyType !== 'symbol') {
434
+ strKey = this._hashFn(key);
435
+ } else {
436
+ if (keyType === 'number') {
437
+ strKey = <string>key;
438
+ } else {
439
+ strKey = <string>key;
440
+ }
441
+ }
442
+ return strKey;
443
+ }
444
+ }
445
+
446
+ /**
447
+ * Hash-based map that preserves insertion order via a doubly-linked list.
448
+ * @remarks Time O(1), Space O(1)
449
+ * @template K
450
+ * @template V
451
+ * @template R
452
+ * @example examples will be generated by unit test
453
+ */
454
+ export class LinkedHashMap<K = any, V = any, R = [K, V]> extends IterableEntryBase<K, V> {
455
+ protected readonly _sentinel: HashMapLinkedNode<K, V | undefined>;
456
+
457
+ /**
458
+ * Create a LinkedHashMap and optionally bulk-insert entries.
459
+ * @remarks Time O(N), Space O(N)
460
+ * @param [entryOrRawElements] - Iterable of entries or raw elements to insert.
461
+ * @param [options] - Options: hash functions and optional record-to-entry converter.
462
+ * @returns New LinkedHashMap instance.
463
+ */
464
+ constructor(entryOrRawElements: Iterable<R | [K, V]> = [], options?: LinkedHashMapOptions<K, V, R>) {
465
+ super();
466
+ this._sentinel = <HashMapLinkedNode<K, V>>{};
467
+ this._sentinel.prev = this._sentinel.next = this._head = this._tail = this._sentinel;
468
+
469
+ if (options) {
470
+ const { hashFn, objHashFn, toEntryFn } = options;
471
+ if (hashFn) this._hashFn = hashFn;
472
+ if (objHashFn) this._objHashFn = objHashFn;
473
+ if (toEntryFn) this._toEntryFn = toEntryFn;
474
+ }
475
+
476
+ if (entryOrRawElements) this.setMany(entryOrRawElements);
477
+ }
478
+
479
+ protected _hashFn: (key: K) => string = (key: K) => String(key);
480
+ get hashFn(): (key: K) => string {
481
+ return this._hashFn;
482
+ }
483
+
484
+ protected _objHashFn: (key: K) => object = (key: K) => <object>key;
485
+
486
+ /**
487
+ * Get the hash function for object/weak keys.
488
+ * @remarks Time O(1), Space O(1)
489
+ * @returns Object-hash function.
490
+ */
491
+ get objHashFn(): (key: K) => object {
492
+ return this._objHashFn;
493
+ }
494
+
495
+ protected _noObjMap: Record<string, HashMapLinkedNode<K, V | undefined>> = {};
496
+
497
+ /**
498
+ * Get the internal record for non-object keys.
499
+ * @remarks Time O(1), Space O(1)
500
+ * @returns Record of hash→node.
501
+ */
502
+ get noObjMap(): Record<string, HashMapLinkedNode<K, V | undefined>> {
503
+ return this._noObjMap;
504
+ }
505
+
506
+ protected _objMap = new WeakMap<object, HashMapLinkedNode<K, V | undefined>>();
507
+ get objMap(): WeakMap<object, HashMapLinkedNode<K, V | undefined>> {
508
+ return this._objMap;
509
+ }
510
+
511
+ protected _head: HashMapLinkedNode<K, V | undefined>;
512
+
513
+ /**
514
+ * Get the head node (first entry) sentinel link.
515
+ * @remarks Time O(1), Space O(1)
516
+ * @returns Head node or sentinel.
517
+ */
518
+ get head(): HashMapLinkedNode<K, V | undefined> {
519
+ return this._head;
520
+ }
521
+
522
+ protected _tail: HashMapLinkedNode<K, V | undefined>;
523
+
524
+ /**
525
+ * Get the tail node (last entry) sentinel link.
526
+ * @remarks Time O(1), Space O(1)
527
+ * @returns Tail node or sentinel.
528
+ */
529
+ get tail(): HashMapLinkedNode<K, V | undefined> {
530
+ return this._tail;
531
+ }
532
+
533
+ protected _toEntryFn?: (rawElement: R) => [K, V] = (rawElement: R) => {
534
+ if (this.isEntry(rawElement)) {
535
+ return rawElement;
536
+ }
537
+ throw new Error(
538
+ 'If `entryOrRawElements` does not adhere to [key,value], provide `options.toEntryFn` to transform raw records.'
539
+ );
540
+ };
541
+ get toEntryFn() {
542
+ return this._toEntryFn;
543
+ }
544
+
545
+ protected _size = 0;
546
+ get size() {
547
+ return this._size;
548
+ }
549
+
550
+ /**
551
+ * Get the first [key, value] pair.
552
+ * @remarks Time O(1), Space O(1)
553
+ * @returns First entry or undefined when empty.
554
+ */
555
+ get first() {
556
+ if (this._size === 0) return;
557
+ return <[K, V]>[this.head.key, this.head.value];
558
+ }
559
+
560
+ /**
561
+ * Get the last [key, value] pair.
562
+ * @remarks Time O(1), Space O(1)
563
+ * @returns Last entry or undefined when empty.
564
+ */
565
+ get last() {
566
+ if (this._size === 0) return;
567
+ return <[K, V]>[this.tail.key, this.tail.value];
568
+ }
569
+
570
+ /**
571
+ * Iterate from head → tail.
572
+ * @remarks Time O(N), Space O(1)
573
+ * @returns Iterator of [key, value].
574
+ */
575
+ *begin() {
576
+ let node = this.head;
577
+ while (node !== this._sentinel) {
578
+ yield [node.key, node.value];
579
+ node = node.next;
580
+ }
581
+ }
582
+
583
+ /**
584
+ * Iterate from tail → head.
585
+ * @remarks Time O(N), Space O(1)
586
+ * @returns Iterator of [key, value].
587
+ */
588
+ *reverseBegin() {
589
+ let node = this.tail;
590
+ while (node !== this._sentinel) {
591
+ yield [node.key, node.value];
592
+ node = node.prev;
593
+ }
594
+ }
595
+
596
+ /**
597
+ * Insert or replace a single entry; preserves insertion order.
598
+ * @remarks Time O(1), Space O(1)
599
+ * @param key - Key.
600
+ * @param [value] - Value.
601
+ * @returns True when the operation succeeds.
602
+ */
603
+ set(key: K, value?: V): boolean {
604
+ let node: HashMapLinkedNode<K, V | undefined> | undefined;
605
+ const isNewKey = !this.has(key);
606
+
607
+ if (isWeakKey(key)) {
608
+ const hash = this._objHashFn(key);
609
+ node = this.objMap.get(hash);
610
+ if (!node && isNewKey) {
611
+ node = { key: <K>hash, value, prev: this.tail, next: this._sentinel };
612
+ this.objMap.set(hash, node);
613
+ } else if (node) {
614
+ node.value = value;
615
+ }
616
+ } else {
617
+ const hash = this._hashFn(key);
618
+ node = this.noObjMap[hash];
619
+ if (!node && isNewKey) {
620
+ this.noObjMap[hash] = node = { key, value, prev: this.tail, next: this._sentinel };
621
+ } else if (node) {
622
+ node.value = value;
623
+ }
624
+ }
625
+
626
+ if (node && isNewKey) {
627
+ if (this._size === 0) {
628
+ this._head = node;
629
+ this._sentinel.next = node;
630
+ } else {
631
+ this.tail.next = node;
632
+ node.prev = this.tail;
633
+ }
634
+ this._tail = node;
635
+ this._sentinel.prev = node;
636
+ this._size++;
637
+ }
638
+
639
+ return true;
640
+ }
641
+
642
+ setMany(entryOrRawElements: Iterable<R | [K, V]>): boolean[] {
643
+ const results: boolean[] = [];
644
+ for (const rawEle of entryOrRawElements) {
645
+ let key: K | undefined, value: V | undefined;
646
+ if (this.isEntry(rawEle)) [key, value] = rawEle;
647
+ else if (this._toEntryFn) [key, value] = this._toEntryFn(rawEle);
648
+ if (key !== undefined && value !== undefined) results.push(this.set(key, value));
649
+ }
650
+ return results;
651
+ }
652
+
653
+ override has(key: K): boolean {
654
+ if (isWeakKey(key)) {
655
+ const hash = this._objHashFn(key);
656
+ return this.objMap.has(hash);
657
+ }
658
+ const hash = this._hashFn(key);
659
+ return hash in this.noObjMap;
660
+ }
661
+
662
+ override get(key: K): V | undefined {
663
+ if (isWeakKey(key)) {
664
+ const hash = this._objHashFn(key);
665
+ const node = this.objMap.get(hash);
666
+ return node ? node.value : undefined;
667
+ }
668
+ const hash = this._hashFn(key);
669
+ const node = this.noObjMap[hash];
670
+ return node ? node.value : undefined;
671
+ }
672
+
673
+ /**
674
+ * Get the value at a given index in insertion order.
675
+ * @remarks Time O(N), Space O(1)
676
+ * @param index - Zero-based index.
677
+ * @returns Value at the index.
678
+ */
679
+ at(index: number): V | undefined {
680
+ rangeCheck(index, 0, this._size - 1);
681
+ let node = this.head;
682
+ while (index--) node = node.next;
683
+ return node.value;
684
+ }
685
+
686
+ delete(key: K): boolean {
687
+ let node: HashMapLinkedNode<K, V | undefined> | undefined;
688
+ if (isWeakKey(key)) {
689
+ const hash = this._objHashFn(key);
690
+ node = this.objMap.get(hash);
691
+ if (!node) return false;
692
+ this.objMap.delete(hash);
693
+ } else {
694
+ const hash = this._hashFn(key);
695
+ node = this.noObjMap[hash];
696
+ if (!node) return false;
697
+ delete this.noObjMap[hash];
698
+ }
699
+ return this._deleteNode(node);
700
+ }
701
+
702
+ /**
703
+ * Delete the first entry that matches a predicate.
704
+ * @remarks Time O(N), Space O(1)
705
+ * @param predicate - Function (key, value, index, map) → boolean to decide deletion.
706
+ * @returns True if an entry was removed.
707
+ */
708
+ deleteWhere(predicate: (key: K, value: V | undefined, index: number, map: this) => boolean): boolean {
709
+ let node = this._head;
710
+ let i = 0;
711
+ while (node !== this._sentinel) {
712
+ const cur = node;
713
+ node = node.next;
714
+ if (predicate(cur.key as K, cur.value as V | undefined, i++, this)) {
715
+ if (isWeakKey(cur.key as unknown as object)) {
716
+ this._objMap.delete(cur.key as unknown as object);
717
+ } else {
718
+ const hash = this._hashFn(cur.key as K);
719
+ delete this._noObjMap[hash];
720
+ }
721
+ return this._deleteNode(cur);
722
+ }
723
+ }
724
+ return false;
725
+ }
726
+
727
+ /**
728
+ * Delete the entry at a given index.
729
+ * @remarks Time O(N), Space O(1)
730
+ * @param index - Zero-based index.
731
+ * @returns True if removed.
732
+ */
733
+ deleteAt(index: number): boolean {
734
+ rangeCheck(index, 0, this._size - 1);
735
+ let node = this.head;
736
+ while (index--) node = node.next;
737
+ return this._deleteNode(node);
738
+ }
739
+
740
+ isEmpty(): boolean {
741
+ return this._size === 0;
742
+ }
743
+
744
+ isEntry(rawElement: any): rawElement is [K, V] {
745
+ return Array.isArray(rawElement) && rawElement.length === 2;
746
+ }
747
+
748
+ clear(): void {
749
+ this._noObjMap = {};
750
+ this._size = 0;
751
+ this._head = this._tail = this._sentinel.prev = this._sentinel.next = this._sentinel;
752
+ }
753
+
754
+ clone(): any {
755
+ const opts = { hashFn: this._hashFn, objHashFn: this._objHashFn };
756
+ return this._createLike<[K, V], [K, V], [K, V]>(this, opts);
757
+ }
758
+
759
+ filter(predicate: EntryCallback<K, V, boolean>, thisArg?: any): any {
760
+ const out = this._createLike<K, V, [K, V]>();
761
+ let index = 0;
762
+ for (const [key, value] of this) {
763
+ if (predicate.call(thisArg, value, key, index, this)) out.set(key, value);
764
+ index++;
765
+ }
766
+ return out;
767
+ }
768
+
769
+ /**
770
+ * Map each entry to a new [key, value] pair and preserve order.
771
+ * @remarks Time O(N), Space O(N)
772
+ * @template MK
773
+ * @template MV
774
+ * @param callback - Mapping function (key, value, index, map) → [newKey, newValue].
775
+ * @param [thisArg] - Value for `this` inside the callback.
776
+ * @returns A new map of the same class with transformed entries.
777
+ */
778
+ map<MK, MV>(callback: EntryCallback<K, V, [MK, MV]>, thisArg?: any): any {
779
+ const out = this._createLike<MK, MV, [MK, MV]>();
780
+ let index = 0;
781
+ for (const [key, value] of this) {
782
+ const [newKey, newValue] = callback.call(thisArg, value, key, index, this);
783
+ out.set(newKey, newValue);
784
+ index++;
785
+ }
786
+ return out;
787
+ }
788
+
789
+ protected *_getIterator(): IterableIterator<[K, V]> {
790
+ let node = this.head;
791
+ while (node !== this._sentinel) {
792
+ yield [node.key, node.value] as [K, V];
793
+ node = node.next;
794
+ }
795
+ }
796
+
797
+ protected _deleteNode(node: HashMapLinkedNode<K, V | undefined>): boolean {
798
+ const { prev, next } = node;
799
+ prev.next = next;
800
+ next.prev = prev;
801
+
802
+ if (node === this.head) this._head = next;
803
+ if (node === this.tail) this._tail = prev;
804
+
805
+ this._size -= 1;
806
+ return true;
807
+ }
808
+
809
+ protected _createLike<TK = K, TV = V, TR = [TK, TV]>(entries: Iterable<[TK, TV] | TR> = [], options?: any): any {
810
+ const Ctor = this.constructor as new (e?: Iterable<[TK, TV] | TR>, o?: any) => any;
811
+ return new Ctor(entries, options);
812
+ }
813
+ }