-
Notifications
You must be signed in to change notification settings - Fork 1
/
big_map.js
213 lines (184 loc) · 3.96 KB
/
big_map.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
/**
* @brief Big Map class that implements the public API of Map
*/
class BigMap {
constructor ( ...parameters ) {
this.maps = [new Map( ...parameters )];
this._limit = 14000000;
}
/**
* @brief Sets the value for the given key
*
* @details This function will create a new Map as is needed
* A new map will be created every 8,000,000 keys
*
* @param {*} key - the key to set
* @param {*} value - the value to set
*
* @return *
*/
set( key, value ) {
let mapToSet = null;
this.maps.forEach( ( map ) => {
if ( map.has( key ) )
mapToSet = map;
});
if ( mapToSet === null ) {
mapToSet = this.maps[this.maps.length - 1];
if ( mapToSet.size >= this._limit ) {
mapToSet = new Map();
this.maps.push( mapToSet );
}
}
return mapToSet.set( key, value );
}
/**
* @brief Gets a value given a key
*
* @param {*} key - the key to get
*
* @return {*} - element that was set
*/
get( key ) {
const map = this._findMapWithKey( key );
if ( typeof map === 'undefined' )
return map;
return map.get( key );
}
/**
* @brief Deletes a value given a key
*
* @details This will remove the Map if it becomes empty when the key is deleted
*
* @param {*} key - the key of the value to delete
*
* @return * - The value that was deleted
*/
delete( key ) {
const map = this._findMapWithKey( key );
if ( typeof map === 'undefined' )
return false;
const result = map.delete( key );
if ( map.size === 0 && this.maps.length !== 1 )
this.maps.splice( this.maps.indexOf( map ), 1 );
return result;
}
/**
* @brief Checks if a key exists
*
* @param {*} key - the key to check if exists
*
* @return {Boolean} - a flag whether the key exists
*/
has( key ) {
return typeof this._findMapWithKey( key ) !== 'undefined';
}
/**
* @brief Clears all the maps
*
* @details This will set a new Map to work with
*/
clear() {
const oldMaps = this.maps;
this.maps = [new Map()];
for ( let map of oldMaps )
map.clear();
}
/**
* @brief Returns the current size of the BigMap
*
* @return {Number}
*/
get size() {
let size = 0;
for ( let map of this.maps )
size += map.size;
return size;
}
/**
* @param {Function} callbackFn - function that will be called
* @param {*} thisArg - this argument to bind to
*/
forEach ( callbackFn, thisArg ) {
if ( thisArg )
for ( const result of this ) {
const key = result[0];
const value = result[1];
callbackFn.call( this, value, key, this );
}
else
for ( const result of this ) {
const key = result[0];
const value = result[1];
callbackFn( value, key, this );
}
}
/**
* @brief Returns an Iterator that will return all the BigMap Entries
*
* @return {Iterator}
*/
entries() {
return this._propIterator( 'entries' );
}
/**
* @brief Returns an Iterator that will return all the BigMap Keys
*
* @return {Iterator}
*/
keys() {
return this._propIterator( 'keys' );
}
/**
* @brief Returns an Iterator that will return all the BigMap Values
*
* @return {Iterator}
*/
values() {
return this._propIterator( 'values' );
}
/**
* @brief Called when doing for...of loops
*
* @return {Generator}
*/
*[Symbol.iterator] () {
for ( const map of this.maps ) {
for ( const value of map )
yield value;
}
}
/**
* @brief Returns an Iterator for the given element
*
* @private
*
* @return {Iterator|Object}
*/
_propIterator( elementToGet ) {
const that = this;
return {
*[Symbol.iterator]() {
for ( const map of that.maps )
for ( const element of map[elementToGet]() )
yield element;
}
};
}
/**
* @brief Finds which map exactly has the given key and returns it
*
* @private
* @param {*} key
*
* @return {Map}
*/
_findMapWithKey( key ) {
for ( let index = this.maps.length - 1; index >= 0; index-- ) {
const map = this.maps[index];
if ( map.has( key ) )
return map;
}
}
}
module.exports = BigMap;