OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 patch class HashMap<K, V> { | 5 patch class HashMap<K, V> { |
6 /* patch */ factory HashMap({ bool equals(K key1, K key2), | |
7 int hashCode(K key) }) { | |
8 if (hashCode == null) { | |
9 if (equals == null) { | |
10 return new _HashMapImpl<K, V>(); | |
11 } | |
12 if (identical(identical, equals)) { | |
13 return new _IdentityHashMap<K, V>(); | |
14 } | |
15 hashCode = _defaultHashCode; | |
16 } else if (equals == null) { | |
17 equals = _defaultEquals; | |
18 } | |
19 return new _CustomHashMap<K, V>(equals, hashCode); | |
20 } | |
21 } | |
22 | |
23 const int _MODIFICATION_COUNT_MASK = 0x3fffffff; | |
24 | |
25 class _HashMapImpl<K, V> implements HashMap<K, V> { | |
26 static const int _INITIAL_CAPACITY = 8; | 6 static const int _INITIAL_CAPACITY = 8; |
| 7 static const int _MODIFICATION_COUNT_MASK = 0x3fffffff; |
27 | 8 |
28 int _elementCount = 0; | 9 int _elementCount = 0; |
29 List<_HashMapEntry> _buckets = new List(_INITIAL_CAPACITY); | 10 List<_HashMapEntry> _buckets = new List(_INITIAL_CAPACITY); |
30 int _modificationCount = 0; | 11 int _modificationCount = 0; |
31 | 12 |
32 int get length => _elementCount; | 13 /* patch */ HashMap._internal(); |
33 bool get isEmpty => _elementCount == 0; | |
34 bool get isNotEmpty => _elementCount != 0; | |
35 | 14 |
36 Iterable<K> get keys => new _HashMapKeyIterable<K>(this); | 15 /* patch */ int get length => _elementCount; |
37 Iterable<V> get values => new _HashMapValueIterable<V>(this); | 16 /* patch */ bool get isEmpty => _elementCount == 0; |
| 17 /* patch */ bool get isNotEmpty => _elementCount != 0; |
38 | 18 |
39 bool containsKey(Object key) { | 19 /* patch */ Iterable<K> get keys => new _HashMapKeyIterable<K>(this); |
| 20 /* patch */ Iterable<V> get values => new _HashMapValueIterable<V>(this); |
| 21 |
| 22 /* patch */ bool containsKey(Object key) { |
40 int hashCode = key.hashCode; | 23 int hashCode = key.hashCode; |
41 List buckets = _buckets; | 24 List buckets = _buckets; |
42 int index = hashCode & (buckets.length - 1); | 25 int index = hashCode & (buckets.length - 1); |
43 _HashMapEntry entry = buckets[index]; | 26 _HashMapEntry entry = buckets[index]; |
44 while (entry != null) { | 27 while (entry != null) { |
45 if (hashCode == entry.hashCode && entry.key == key) return true; | 28 if (hashCode == entry.hashCode && entry.key == key) return true; |
46 entry = entry.next; | 29 entry = entry.next; |
47 } | 30 } |
48 return false; | 31 return false; |
49 } | 32 } |
50 | 33 |
51 bool containsValue(Object value) { | 34 /* patch */ bool containsValue(Object value) { |
52 List buckets = _buckets; | 35 List buckets = _buckets; |
53 int length = buckets.length; | 36 int length = buckets.length; |
54 for (int i = 0; i < length; i++) { | 37 for (int i = 0; i < length; i++) { |
55 _HashMapEntry entry = buckets[i]; | 38 _HashMapEntry entry = buckets[i]; |
56 while (entry != null) { | 39 while (entry != null) { |
57 if (entry.value == value) return true; | 40 if (entry.value == value) return true; |
58 entry = entry.next; | 41 entry = entry.next; |
59 } | 42 } |
60 } | 43 } |
61 return false; | 44 return false; |
62 } | 45 } |
63 | 46 |
64 V operator[](Object key) { | 47 /* patch */ V operator[](Object key) { |
65 int hashCode = key.hashCode; | 48 int hashCode = key.hashCode; |
66 List buckets = _buckets; | 49 List buckets = _buckets; |
67 int index = hashCode & (buckets.length - 1); | 50 int index = hashCode & (buckets.length - 1); |
68 _HashMapEntry entry = buckets[index]; | 51 _HashMapEntry entry = buckets[index]; |
69 while (entry != null) { | 52 while (entry != null) { |
70 if (hashCode == entry.hashCode && entry.key == key) { | 53 if (hashCode == entry.hashCode && entry.key == key) { |
71 return entry.value; | 54 return entry.value; |
72 } | 55 } |
73 entry = entry.next; | 56 entry = entry.next; |
74 } | 57 } |
75 return null; | 58 return null; |
76 } | 59 } |
77 | 60 |
78 void operator []=(K key, V value) { | 61 /* patch */ void operator []=(K key, V value) { |
79 int hashCode = key.hashCode; | 62 int hashCode = key.hashCode; |
80 List buckets = _buckets; | 63 List buckets = _buckets; |
81 int length = buckets.length; | 64 int length = buckets.length; |
82 int index = hashCode & (length - 1); | 65 int index = hashCode & (length - 1); |
83 _HashMapEntry entry = buckets[index]; | 66 _HashMapEntry entry = buckets[index]; |
84 while (entry != null) { | 67 while (entry != null) { |
85 if (hashCode == entry.hashCode && entry.key == key) { | 68 if (hashCode == entry.hashCode && entry.key == key) { |
86 entry.value = value; | 69 entry.value = value; |
87 return; | 70 return; |
88 } | 71 } |
89 entry = entry.next; | 72 entry = entry.next; |
90 } | 73 } |
91 _addEntry(buckets, index, length, key, value, hashCode); | 74 _addEntry(buckets, index, length, key, value, hashCode); |
92 } | 75 } |
93 | 76 |
94 V putIfAbsent(K key, V ifAbsent()) { | 77 /* patch */ V putIfAbsent(K key, V ifAbsent()) { |
95 int hashCode = key.hashCode; | 78 int hashCode = key.hashCode; |
96 List buckets = _buckets; | 79 List buckets = _buckets; |
97 int length = buckets.length; | 80 int length = buckets.length; |
98 int index = hashCode & (length - 1); | 81 int index = hashCode & (length - 1); |
99 _HashMapEntry entry = buckets[index]; | 82 _HashMapEntry entry = buckets[index]; |
100 while (entry != null) { | 83 while (entry != null) { |
101 if (hashCode == entry.hashCode && entry.key == key) { | 84 if (hashCode == entry.hashCode && entry.key == key) { |
102 return entry.value; | 85 return entry.value; |
103 } | 86 } |
104 entry = entry.next; | 87 entry = entry.next; |
105 } | 88 } |
106 int stamp = _modificationCount; | 89 int stamp = _modificationCount; |
107 V value = ifAbsent(); | 90 V value = ifAbsent(); |
108 if (stamp == _modificationCount) { | 91 if (stamp == _modificationCount) { |
109 _addEntry(buckets, index, length, key, value, hashCode); | 92 _addEntry(buckets, index, length, key, value, hashCode); |
110 } else { | 93 } else { |
111 this[key] = value; | 94 this[key] = value; |
112 } | 95 } |
113 return value; | 96 return value; |
114 } | 97 } |
115 | 98 |
116 void addAll(Map<K, V> other) { | 99 /* patch */ void addAll(Map<K, V> other) { |
117 other.forEach((K key, V value) { | 100 other.forEach((K key, V value) { |
118 this[key] = value; | 101 this[key] = value; |
119 }); | 102 }); |
120 } | 103 } |
121 | 104 |
122 void forEach(void action(K key, V value)) { | 105 /* patch */ void forEach(void action(K key, V value)) { |
123 int stamp = _modificationCount; | 106 int stamp = _modificationCount; |
124 List buckets = _buckets; | 107 List buckets = _buckets; |
125 int length = buckets.length; | 108 int length = buckets.length; |
126 for (int i = 0; i < length; i++) { | 109 for (int i = 0; i < length; i++) { |
127 _HashMapEntry entry = buckets[i]; | 110 _HashMapEntry entry = buckets[i]; |
128 while (entry != null) { | 111 while (entry != null) { |
129 action(entry.key, entry.value); | 112 action(entry.key, entry.value); |
130 if (stamp != _modificationCount) { | 113 if (stamp != _modificationCount) { |
131 throw new ConcurrentModificationError(this); | 114 throw new ConcurrentModificationError(this); |
132 } | 115 } |
133 entry = entry.next; | 116 entry = entry.next; |
134 } | 117 } |
135 } | 118 } |
136 } | 119 } |
137 | 120 |
138 V remove(Object key) { | 121 /* patch */ V remove(Object key) { |
139 int hashCode = key.hashCode; | 122 int hashCode = key.hashCode; |
140 List buckets = _buckets; | 123 List buckets = _buckets; |
141 int index = hashCode & (buckets.length - 1); | 124 int index = hashCode & (buckets.length - 1); |
142 _HashMapEntry entry = buckets[index]; | 125 _HashMapEntry entry = buckets[index]; |
143 _HashMapEntry previous = null; | 126 _HashMapEntry previous = null; |
144 while (entry != null) { | 127 while (entry != null) { |
145 _HashMapEntry next = entry.next; | 128 _HashMapEntry next = entry.next; |
146 if (hashCode == entry.hashCode && entry.key == key) { | 129 if (hashCode == entry.hashCode && entry.key == key) { |
147 if (previous == null) { | 130 if (previous == null) { |
148 buckets[index] = next; | 131 buckets[index] = next; |
149 } else { | 132 } else { |
150 previous.next = next; | 133 previous.next = next; |
151 } | 134 } |
152 _elementCount--; | 135 _elementCount--; |
153 _modificationCount = | 136 _modificationCount = |
154 (_modificationCount + 1) & _MODIFICATION_COUNT_MASK; | 137 (_modificationCount + 1) & _MODIFICATION_COUNT_MASK; |
155 return entry.value; | 138 return entry.value; |
156 } | 139 } |
157 previous = entry; | 140 previous = entry; |
158 entry = next; | 141 entry = next; |
159 } | 142 } |
160 return null; | 143 return null; |
161 } | 144 } |
162 | 145 |
163 void clear() { | 146 /* patch */ void clear() { |
164 _elementCount = 0; | 147 _elementCount = 0; |
165 _buckets = new List(_INITIAL_CAPACITY); | 148 _buckets = new List(_INITIAL_CAPACITY); |
166 _modificationCount = (_modificationCount + 1) & _MODIFICATION_COUNT_MASK; | 149 _modificationCount = (_modificationCount + 1) & _MODIFICATION_COUNT_MASK; |
167 } | 150 } |
168 | 151 |
169 void _addEntry(List buckets, int index, int length, | 152 void _addEntry(List buckets, int index, int length, |
170 K key, V value, int hashCode) { | 153 K key, V value, int hashCode) { |
171 _HashMapEntry entry = | 154 _HashMapEntry entry = |
172 new _HashMapEntry(key, value, hashCode, buckets[index]); | 155 new _HashMapEntry(key, value, hashCode, buckets[index]); |
173 buckets[index] = entry; | 156 buckets[index] = entry; |
(...skipping 18 matching lines...) Expand all Loading... |
192 int index = hashCode & (newLength - 1); | 175 int index = hashCode & (newLength - 1); |
193 entry.next = newBuckets[index]; | 176 entry.next = newBuckets[index]; |
194 newBuckets[index] = entry; | 177 newBuckets[index] = entry; |
195 entry = next; | 178 entry = next; |
196 } | 179 } |
197 } | 180 } |
198 _buckets = newBuckets; | 181 _buckets = newBuckets; |
199 } | 182 } |
200 } | 183 } |
201 | 184 |
202 class _CustomHashMap<K, V> extends _HashMapImpl<K, V> { | |
203 final Function _equals; | |
204 final Function _hashCode; | |
205 _CustomHashMap(this._equals, this._hashCode); | |
206 | |
207 bool containsKey(Object key) { | |
208 int hashCode = _hashCode(key); | |
209 List buckets = _buckets; | |
210 int index = hashCode & (buckets.length - 1); | |
211 _HashMapEntry entry = buckets[index]; | |
212 while (entry != null) { | |
213 if (hashCode == entry.hashCode && _equals(entry.key, key)) return true; | |
214 entry = entry.next; | |
215 } | |
216 return false; | |
217 } | |
218 | |
219 V operator[](Object key) { | |
220 int hashCode = _hashCode(key); | |
221 List buckets = _buckets; | |
222 int index = hashCode & (buckets.length - 1); | |
223 _HashMapEntry entry = buckets[index]; | |
224 while (entry != null) { | |
225 if (hashCode == entry.hashCode && _equals(entry.key, key)) { | |
226 return entry.value; | |
227 } | |
228 entry = entry.next; | |
229 } | |
230 return null; | |
231 } | |
232 | |
233 void operator []=(K key, V value) { | |
234 int hashCode = _hashCode(key); | |
235 List buckets = _buckets; | |
236 int length = buckets.length; | |
237 int index = hashCode & (length - 1); | |
238 _HashMapEntry entry = buckets[index]; | |
239 while (entry != null) { | |
240 if (hashCode == entry.hashCode && _equals(entry.key, key)) { | |
241 entry.value = value; | |
242 return; | |
243 } | |
244 entry = entry.next; | |
245 } | |
246 _addEntry(buckets, index, length, key, value, hashCode); | |
247 } | |
248 | |
249 V putIfAbsent(K key, V ifAbsent()) { | |
250 int hashCode = _hashCode(key); | |
251 List buckets = _buckets; | |
252 int length = buckets.length; | |
253 int index = hashCode & (length - 1); | |
254 _HashMapEntry entry = buckets[index]; | |
255 while (entry != null) { | |
256 if (hashCode == entry.hashCode && _equals(entry.key, key)) { | |
257 return entry.value; | |
258 } | |
259 entry = entry.next; | |
260 } | |
261 int stamp = _modificationCount; | |
262 V value = ifAbsent(); | |
263 if (stamp == _modificationCount) { | |
264 _addEntry(buckets, index, length, key, value, hashCode); | |
265 } else { | |
266 this[key] = value; | |
267 } | |
268 return value; | |
269 } | |
270 | |
271 V remove(Object key) { | |
272 int hashCode = _hashCode(key); | |
273 List buckets = _buckets; | |
274 int index = hashCode & (buckets.length - 1); | |
275 _HashMapEntry entry = buckets[index]; | |
276 _HashMapEntry previous = null; | |
277 while (entry != null) { | |
278 _HashMapEntry next = entry.next; | |
279 if (hashCode == entry.hashCode && _equals(entry.key, key)) { | |
280 if (previous == null) { | |
281 buckets[index] = next; | |
282 } else { | |
283 previous.next = next; | |
284 } | |
285 _elementCount--; | |
286 _modificationCount = | |
287 (_modificationCount + 1) & _MODIFICATION_COUNT_MASK; | |
288 return entry.value; | |
289 } | |
290 previous = entry; | |
291 entry = next; | |
292 } | |
293 return null; | |
294 } | |
295 } | |
296 | |
297 class _IdentityHashMap<K, V> extends _HashMapImpl<K, V> { | |
298 bool containsKey(Object key) { | |
299 int hashCode = key.hashCode; | |
300 List buckets = _buckets; | |
301 int index = hashCode & (buckets.length - 1); | |
302 _HashMapEntry entry = buckets[index]; | |
303 while (entry != null) { | |
304 if (hashCode == entry.hashCode && identical(entry.key, key)) return true; | |
305 entry = entry.next; | |
306 } | |
307 return false; | |
308 } | |
309 | |
310 V operator[](Object key) { | |
311 int hashCode = key.hashCode; | |
312 List buckets = _buckets; | |
313 int index = hashCode & (buckets.length - 1); | |
314 _HashMapEntry entry = buckets[index]; | |
315 while (entry != null) { | |
316 if (hashCode == entry.hashCode && identical(entry.key, key)) { | |
317 return entry.value; | |
318 } | |
319 entry = entry.next; | |
320 } | |
321 return null; | |
322 } | |
323 | |
324 void operator []=(K key, V value) { | |
325 int hashCode = key.hashCode; | |
326 List buckets = _buckets; | |
327 int length = buckets.length; | |
328 int index = hashCode & (length - 1); | |
329 _HashMapEntry entry = buckets[index]; | |
330 while (entry != null) { | |
331 if (hashCode == entry.hashCode && identical(entry.key, key)) { | |
332 entry.value = value; | |
333 return; | |
334 } | |
335 entry = entry.next; | |
336 } | |
337 _addEntry(buckets, index, length, key, value, hashCode); | |
338 } | |
339 | |
340 V putIfAbsent(K key, V ifAbsent()) { | |
341 int hashCode = key.hashCode; | |
342 List buckets = _buckets; | |
343 int length = buckets.length; | |
344 int index = hashCode & (length - 1); | |
345 _HashMapEntry entry = buckets[index]; | |
346 while (entry != null) { | |
347 if (hashCode == entry.hashCode && identical(entry.key, key)) { | |
348 return entry.value; | |
349 } | |
350 entry = entry.next; | |
351 } | |
352 int stamp = _modificationCount; | |
353 V value = ifAbsent(); | |
354 if (stamp == _modificationCount) { | |
355 _addEntry(buckets, index, length, key, value, hashCode); | |
356 } else { | |
357 this[key] = value; | |
358 } | |
359 return value; | |
360 } | |
361 | |
362 V remove(Object key) { | |
363 int hashCode = key.hashCode; | |
364 List buckets = _buckets; | |
365 int index = hashCode & (buckets.length - 1); | |
366 _HashMapEntry entry = buckets[index]; | |
367 _HashMapEntry previous = null; | |
368 while (entry != null) { | |
369 _HashMapEntry next = entry.next; | |
370 if (hashCode == entry.hashCode && identical(entry.key, key)) { | |
371 if (previous == null) { | |
372 buckets[index] = next; | |
373 } else { | |
374 previous.next = next; | |
375 } | |
376 _elementCount--; | |
377 _modificationCount = | |
378 (_modificationCount + 1) & _MODIFICATION_COUNT_MASK; | |
379 return entry.value; | |
380 } | |
381 previous = entry; | |
382 entry = next; | |
383 } | |
384 return null; | |
385 } | |
386 } | |
387 | |
388 | |
389 class _HashMapEntry { | 185 class _HashMapEntry { |
390 final key; | 186 final key; |
391 var value; | 187 var value; |
392 final int hashCode; | 188 final int hashCode; |
393 _HashMapEntry next; | 189 _HashMapEntry next; |
394 _HashMapEntry(this.key, this.value, this.hashCode, this.next); | 190 _HashMapEntry(this.key, this.value, this.hashCode, this.next); |
395 } | 191 } |
396 | 192 |
397 abstract class _HashMapIterable<E> extends IterableBase<E> { | 193 abstract class _HashMapIterable<E> extends IterableBase<E> { |
398 final HashMap _map; | 194 final HashMap _map; |
(...skipping 1112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1511 | 1307 |
1512 _LinkedHashMapTable() : super(_INITIAL_CAPACITY); | 1308 _LinkedHashMapTable() : super(_INITIAL_CAPACITY); |
1513 | 1309 |
1514 V _value(int offset) => _table[offset + _VALUE_INDEX]; | 1310 V _value(int offset) => _table[offset + _VALUE_INDEX]; |
1515 void _setValue(int offset, V value) { _table[offset + _VALUE_INDEX] = value; } | 1311 void _setValue(int offset, V value) { _table[offset + _VALUE_INDEX] = value; } |
1516 | 1312 |
1517 _copyEntry(List oldTable, int fromOffset, int toOffset) { | 1313 _copyEntry(List oldTable, int fromOffset, int toOffset) { |
1518 _table[toOffset + _VALUE_INDEX] = oldTable[fromOffset + _VALUE_INDEX]; | 1314 _table[toOffset + _VALUE_INDEX] = oldTable[fromOffset + _VALUE_INDEX]; |
1519 } | 1315 } |
1520 } | 1316 } |
OLD | NEW |