Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(126)

Side by Side Diff: runtime/lib/collection_patch.dart

Issue 23893002: Add custom equals and hashCode for HashMap implementation. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Fix bug in dart2js code. Please review. Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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> {
6 static const int _INITIAL_CAPACITY = 8; 26 static const int _INITIAL_CAPACITY = 8;
7 static const int _MODIFICATION_COUNT_MASK = 0x3fffffff;
8 27
9 int _elementCount = 0; 28 int _elementCount = 0;
10 List<_HashMapEntry> _buckets = new List(_INITIAL_CAPACITY); 29 List<_HashMapEntry> _buckets = new List(_INITIAL_CAPACITY);
11 int _modificationCount = 0; 30 int _modificationCount = 0;
12 31
13 /* patch */ HashMap._internal(); 32 int get length => _elementCount;
33 bool get isEmpty => _elementCount == 0;
34 bool get isNotEmpty => _elementCount != 0;
14 35
15 /* patch */ int get length => _elementCount; 36 Iterable<K> get keys => new _HashMapKeyIterable<K>(this);
16 /* patch */ bool get isEmpty => _elementCount == 0; 37 Iterable<V> get values => new _HashMapValueIterable<V>(this);
17 /* patch */ bool get isNotEmpty => _elementCount != 0;
18 38
19 /* patch */ Iterable<K> get keys => new _HashMapKeyIterable<K>(this); 39 bool containsKey(Object key) {
20 /* patch */ Iterable<V> get values => new _HashMapValueIterable<V>(this);
21
22 /* patch */ bool containsKey(Object key) {
23 int hashCode = key.hashCode; 40 int hashCode = key.hashCode;
24 List buckets = _buckets; 41 List buckets = _buckets;
25 int index = hashCode & (buckets.length - 1); 42 int index = hashCode & (buckets.length - 1);
26 _HashMapEntry entry = buckets[index]; 43 _HashMapEntry entry = buckets[index];
27 while (entry != null) { 44 while (entry != null) {
28 if (hashCode == entry.hashCode && entry.key == key) return true; 45 if (hashCode == entry.hashCode && entry.key == key) return true;
29 entry = entry.next; 46 entry = entry.next;
30 } 47 }
31 return false; 48 return false;
32 } 49 }
33 50
34 /* patch */ bool containsValue(Object value) { 51 bool containsValue(Object value) {
35 List buckets = _buckets; 52 List buckets = _buckets;
36 int length = buckets.length; 53 int length = buckets.length;
37 for (int i = 0; i < length; i++) { 54 for (int i = 0; i < length; i++) {
38 _HashMapEntry entry = buckets[i]; 55 _HashMapEntry entry = buckets[i];
39 while (entry != null) { 56 while (entry != null) {
40 if (entry.value == value) return true; 57 if (entry.value == value) return true;
41 entry = entry.next; 58 entry = entry.next;
42 } 59 }
43 } 60 }
44 return false; 61 return false;
45 } 62 }
46 63
47 /* patch */ V operator[](Object key) { 64 V operator[](Object key) {
48 int hashCode = key.hashCode; 65 int hashCode = key.hashCode;
49 List buckets = _buckets; 66 List buckets = _buckets;
50 int index = hashCode & (buckets.length - 1); 67 int index = hashCode & (buckets.length - 1);
51 _HashMapEntry entry = buckets[index]; 68 _HashMapEntry entry = buckets[index];
52 while (entry != null) { 69 while (entry != null) {
53 if (hashCode == entry.hashCode && entry.key == key) { 70 if (hashCode == entry.hashCode && entry.key == key) {
54 return entry.value; 71 return entry.value;
55 } 72 }
56 entry = entry.next; 73 entry = entry.next;
57 } 74 }
58 return null; 75 return null;
59 } 76 }
60 77
61 /* patch */ void operator []=(K key, V value) { 78 void operator []=(K key, V value) {
62 int hashCode = key.hashCode; 79 int hashCode = key.hashCode;
63 List buckets = _buckets; 80 List buckets = _buckets;
64 int length = buckets.length; 81 int length = buckets.length;
65 int index = hashCode & (length - 1); 82 int index = hashCode & (length - 1);
66 _HashMapEntry entry = buckets[index]; 83 _HashMapEntry entry = buckets[index];
67 while (entry != null) { 84 while (entry != null) {
68 if (hashCode == entry.hashCode && entry.key == key) { 85 if (hashCode == entry.hashCode && entry.key == key) {
69 entry.value = value; 86 entry.value = value;
70 return; 87 return;
71 } 88 }
72 entry = entry.next; 89 entry = entry.next;
73 } 90 }
74 _addEntry(buckets, index, length, key, value, hashCode); 91 _addEntry(buckets, index, length, key, value, hashCode);
75 } 92 }
76 93
77 /* patch */ V putIfAbsent(K key, V ifAbsent()) { 94 V putIfAbsent(K key, V ifAbsent()) {
78 int hashCode = key.hashCode; 95 int hashCode = key.hashCode;
79 List buckets = _buckets; 96 List buckets = _buckets;
80 int length = buckets.length; 97 int length = buckets.length;
81 int index = hashCode & (length - 1); 98 int index = hashCode & (length - 1);
82 _HashMapEntry entry = buckets[index]; 99 _HashMapEntry entry = buckets[index];
83 while (entry != null) { 100 while (entry != null) {
84 if (hashCode == entry.hashCode && entry.key == key) { 101 if (hashCode == entry.hashCode && entry.key == key) {
85 return entry.value; 102 return entry.value;
86 } 103 }
87 entry = entry.next; 104 entry = entry.next;
88 } 105 }
89 int stamp = _modificationCount; 106 int stamp = _modificationCount;
90 V value = ifAbsent(); 107 V value = ifAbsent();
91 if (stamp == _modificationCount) { 108 if (stamp == _modificationCount) {
92 _addEntry(buckets, index, length, key, value, hashCode); 109 _addEntry(buckets, index, length, key, value, hashCode);
93 } else { 110 } else {
94 this[key] = value; 111 this[key] = value;
95 } 112 }
96 return value; 113 return value;
97 } 114 }
98 115
99 /* patch */ void addAll(Map<K, V> other) { 116 void addAll(Map<K, V> other) {
100 other.forEach((K key, V value) { 117 other.forEach((K key, V value) {
101 this[key] = value; 118 this[key] = value;
102 }); 119 });
103 } 120 }
104 121
105 /* patch */ void forEach(void action(K key, V value)) { 122 void forEach(void action(K key, V value)) {
106 int stamp = _modificationCount; 123 int stamp = _modificationCount;
107 List buckets = _buckets; 124 List buckets = _buckets;
108 int length = buckets.length; 125 int length = buckets.length;
109 for (int i = 0; i < length; i++) { 126 for (int i = 0; i < length; i++) {
110 _HashMapEntry entry = buckets[i]; 127 _HashMapEntry entry = buckets[i];
111 while (entry != null) { 128 while (entry != null) {
112 action(entry.key, entry.value); 129 action(entry.key, entry.value);
113 if (stamp != _modificationCount) { 130 if (stamp != _modificationCount) {
114 throw new ConcurrentModificationError(this); 131 throw new ConcurrentModificationError(this);
115 } 132 }
116 entry = entry.next; 133 entry = entry.next;
117 } 134 }
118 } 135 }
119 } 136 }
120 137
121 /* patch */ V remove(Object key) { 138 V remove(Object key) {
122 int hashCode = key.hashCode; 139 int hashCode = key.hashCode;
123 List buckets = _buckets; 140 List buckets = _buckets;
124 int index = hashCode & (buckets.length - 1); 141 int index = hashCode & (buckets.length - 1);
125 _HashMapEntry entry = buckets[index]; 142 _HashMapEntry entry = buckets[index];
126 _HashMapEntry previous = null; 143 _HashMapEntry previous = null;
127 while (entry != null) { 144 while (entry != null) {
128 _HashMapEntry next = entry.next; 145 _HashMapEntry next = entry.next;
129 if (hashCode == entry.hashCode && entry.key == key) { 146 if (hashCode == entry.hashCode && entry.key == key) {
130 if (previous == null) { 147 if (previous == null) {
131 buckets[index] = next; 148 buckets[index] = next;
132 } else { 149 } else {
133 previous.next = next; 150 previous.next = next;
134 } 151 }
135 _elementCount--; 152 _elementCount--;
136 _modificationCount = 153 _modificationCount =
137 (_modificationCount + 1) & _MODIFICATION_COUNT_MASK; 154 (_modificationCount + 1) & _MODIFICATION_COUNT_MASK;
138 return entry.value; 155 return entry.value;
139 } 156 }
140 previous = entry; 157 previous = entry;
141 entry = next; 158 entry = next;
142 } 159 }
143 return null; 160 return null;
144 } 161 }
145 162
146 /* patch */ void clear() { 163 void clear() {
147 _elementCount = 0; 164 _elementCount = 0;
148 _buckets = new List(_INITIAL_CAPACITY); 165 _buckets = new List(_INITIAL_CAPACITY);
149 _modificationCount = (_modificationCount + 1) & _MODIFICATION_COUNT_MASK; 166 _modificationCount = (_modificationCount + 1) & _MODIFICATION_COUNT_MASK;
150 } 167 }
151 168
152 void _addEntry(List buckets, int index, int length, 169 void _addEntry(List buckets, int index, int length,
153 K key, V value, int hashCode) { 170 K key, V value, int hashCode) {
154 _HashMapEntry entry = 171 _HashMapEntry entry =
155 new _HashMapEntry(key, value, hashCode, buckets[index]); 172 new _HashMapEntry(key, value, hashCode, buckets[index]);
156 buckets[index] = entry; 173 buckets[index] = entry;
(...skipping 18 matching lines...) Expand all
175 int index = hashCode & (newLength - 1); 192 int index = hashCode & (newLength - 1);
176 entry.next = newBuckets[index]; 193 entry.next = newBuckets[index];
177 newBuckets[index] = entry; 194 newBuckets[index] = entry;
178 entry = next; 195 entry = next;
179 } 196 }
180 } 197 }
181 _buckets = newBuckets; 198 _buckets = newBuckets;
182 } 199 }
183 } 200 }
184 201
202 class _CustomHashMap<K, V> extends _HashMapImpl<K, V> {
floitsch 2013/09/03 13:59:08 File a bug against the VM asking for customization
Lasse Reichstein Nielsen 2013/09/04 05:59:21 I can avoid the code duplication myself by abstrac
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> {
floitsch 2013/09/03 13:59:08 I'm not sure we need to have Identity maps to be c
Lasse Reichstein Nielsen 2013/09/04 05:59:21 I expect IdentityMap to be the main usage of custo
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
185 class _HashMapEntry { 389 class _HashMapEntry {
186 final key; 390 final key;
187 var value; 391 var value;
188 final int hashCode; 392 final int hashCode;
189 _HashMapEntry next; 393 _HashMapEntry next;
190 _HashMapEntry(this.key, this.value, this.hashCode, this.next); 394 _HashMapEntry(this.key, this.value, this.hashCode, this.next);
191 } 395 }
192 396
193 abstract class _HashMapIterable<E> extends IterableBase<E> { 397 abstract class _HashMapIterable<E> extends IterableBase<E> {
194 final HashMap _map; 398 final HashMap _map;
(...skipping 1112 matching lines...) Expand 10 before | Expand all | Expand 10 after
1307 1511
1308 _LinkedHashMapTable() : super(_INITIAL_CAPACITY); 1512 _LinkedHashMapTable() : super(_INITIAL_CAPACITY);
1309 1513
1310 V _value(int offset) => _table[offset + _VALUE_INDEX]; 1514 V _value(int offset) => _table[offset + _VALUE_INDEX];
1311 void _setValue(int offset, V value) { _table[offset + _VALUE_INDEX] = value; } 1515 void _setValue(int offset, V value) { _table[offset + _VALUE_INDEX] = value; }
1312 1516
1313 _copyEntry(List oldTable, int fromOffset, int toOffset) { 1517 _copyEntry(List oldTable, int fromOffset, int toOffset) {
1314 _table[toOffset + _VALUE_INDEX] = oldTable[fromOffset + _VALUE_INDEX]; 1518 _table[toOffset + _VALUE_INDEX] = oldTable[fromOffset + _VALUE_INDEX];
1315 } 1519 }
1316 } 1520 }
OLDNEW
« no previous file with comments | « no previous file | sdk/lib/_internal/lib/collection_patch.dart » ('j') | sdk/lib/_internal/lib/collection_patch.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698