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 import 'dart:typed_data'; | 5 import 'dart:typed_data'; |
6 import 'dart:_internal' as internal; | 6 import 'dart:_internal' as internal; |
7 | 7 |
8 @patch class HashMap<K, V> { | 8 @patch |
9 @patch factory HashMap({ bool equals(K key1, K key2), | 9 class HashMap<K, V> { |
10 int hashCode(K key), | 10 @patch |
11 bool isValidKey(potentialKey) }) { | 11 factory HashMap( |
| 12 {bool equals(K key1, K key2), |
| 13 int hashCode(K key), |
| 14 bool isValidKey(potentialKey)}) { |
12 if (isValidKey == null) { | 15 if (isValidKey == null) { |
13 if (hashCode == null) { | 16 if (hashCode == null) { |
14 if (equals == null) { | 17 if (equals == null) { |
15 return new _HashMap<K, V>(); | 18 return new _HashMap<K, V>(); |
16 } | 19 } |
17 hashCode = _defaultHashCode; | 20 hashCode = _defaultHashCode; |
18 } else { | 21 } else { |
19 if (identical(identityHashCode, hashCode) && | 22 if (identical(identityHashCode, hashCode) && |
20 identical(identical, equals)) { | 23 identical(identical, equals)) { |
21 return new _IdentityHashMap<K, V>(); | 24 return new _IdentityHashMap<K, V>(); |
22 } | 25 } |
23 if (equals == null) { | 26 if (equals == null) { |
24 equals = _defaultEquals; | 27 equals = _defaultEquals; |
25 } | 28 } |
26 } | 29 } |
27 } else { | 30 } else { |
28 if (hashCode == null) { | 31 if (hashCode == null) { |
29 hashCode = _defaultHashCode; | 32 hashCode = _defaultHashCode; |
30 } | 33 } |
31 if (equals == null) { | 34 if (equals == null) { |
32 equals = _defaultEquals; | 35 equals = _defaultEquals; |
33 } | 36 } |
34 } | 37 } |
35 return new _CustomHashMap<K, V>(equals, hashCode, isValidKey); | 38 return new _CustomHashMap<K, V>(equals, hashCode, isValidKey); |
36 } | 39 } |
37 | 40 |
38 @patch factory HashMap.identity() = _IdentityHashMap<K, V>; | 41 @patch |
| 42 factory HashMap.identity() = _IdentityHashMap<K, V>; |
39 | 43 |
40 Set<K> _newKeySet(); | 44 Set<K> _newKeySet(); |
41 } | 45 } |
42 | 46 |
43 | |
44 const int _MODIFICATION_COUNT_MASK = 0x3fffffff; | 47 const int _MODIFICATION_COUNT_MASK = 0x3fffffff; |
45 | 48 |
46 class _HashMap<K, V> implements HashMap<K, V> { | 49 class _HashMap<K, V> implements HashMap<K, V> { |
47 static const int _INITIAL_CAPACITY = 8; | 50 static const int _INITIAL_CAPACITY = 8; |
48 | 51 |
49 | |
50 int _elementCount = 0; | 52 int _elementCount = 0; |
51 List<_HashMapEntry> _buckets = new List(_INITIAL_CAPACITY); | 53 List<_HashMapEntry> _buckets = new List(_INITIAL_CAPACITY); |
52 int _modificationCount = 0; | 54 int _modificationCount = 0; |
53 | 55 |
54 int get length => _elementCount; | 56 int get length => _elementCount; |
55 bool get isEmpty => _elementCount == 0; | 57 bool get isEmpty => _elementCount == 0; |
56 bool get isNotEmpty => _elementCount != 0; | 58 bool get isNotEmpty => _elementCount != 0; |
57 | 59 |
58 Iterable<K> get keys => new _HashMapKeyIterable<K>(this); | 60 Iterable<K> get keys => new _HashMapKeyIterable<K>(this); |
59 Iterable<V> get values => new _HashMapValueIterable<V>(this); | 61 Iterable<V> get values => new _HashMapValueIterable<V>(this); |
(...skipping 16 matching lines...) Expand all Loading... |
76 for (int i = 0; i < length; i++) { | 78 for (int i = 0; i < length; i++) { |
77 _HashMapEntry entry = buckets[i]; | 79 _HashMapEntry entry = buckets[i]; |
78 while (entry != null) { | 80 while (entry != null) { |
79 if (entry.value == value) return true; | 81 if (entry.value == value) return true; |
80 entry = entry.next; | 82 entry = entry.next; |
81 } | 83 } |
82 } | 84 } |
83 return false; | 85 return false; |
84 } | 86 } |
85 | 87 |
86 V operator[](Object key) { | 88 V operator [](Object key) { |
87 int hashCode = key.hashCode; | 89 int hashCode = key.hashCode; |
88 List buckets = _buckets; | 90 List buckets = _buckets; |
89 int index = hashCode & (buckets.length - 1); | 91 int index = hashCode & (buckets.length - 1); |
90 _HashMapEntry entry = buckets[index]; | 92 _HashMapEntry entry = buckets[index]; |
91 while (entry != null) { | 93 while (entry != null) { |
92 if (hashCode == entry.hashCode && entry.key == key) { | 94 if (hashCode == entry.hashCode && entry.key == key) { |
93 return entry.value; | 95 return entry.value; |
94 } | 96 } |
95 entry = entry.next; | 97 entry = entry.next; |
96 } | 98 } |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
179 } | 181 } |
180 | 182 |
181 void clear() { | 183 void clear() { |
182 _buckets = new List(_INITIAL_CAPACITY); | 184 _buckets = new List(_INITIAL_CAPACITY); |
183 if (_elementCount > 0) { | 185 if (_elementCount > 0) { |
184 _elementCount = 0; | 186 _elementCount = 0; |
185 _modificationCount = (_modificationCount + 1) & _MODIFICATION_COUNT_MASK; | 187 _modificationCount = (_modificationCount + 1) & _MODIFICATION_COUNT_MASK; |
186 } | 188 } |
187 } | 189 } |
188 | 190 |
189 void _removeEntry(_HashMapEntry entry, | 191 void _removeEntry( |
190 _HashMapEntry previousInBucket, | 192 _HashMapEntry entry, _HashMapEntry previousInBucket, int bucketIndex) { |
191 int bucketIndex) { | |
192 if (previousInBucket == null) { | 193 if (previousInBucket == null) { |
193 _buckets[bucketIndex] = entry.next; | 194 _buckets[bucketIndex] = entry.next; |
194 } else { | 195 } else { |
195 previousInBucket.next = entry.next; | 196 previousInBucket.next = entry.next; |
196 } | 197 } |
197 } | 198 } |
198 | 199 |
199 void _addEntry(List buckets, int index, int length, | 200 void _addEntry( |
200 K key, V value, int hashCode) { | 201 List buckets, int index, int length, K key, V value, int hashCode) { |
201 _HashMapEntry entry = | 202 _HashMapEntry entry = |
202 new _HashMapEntry(key, value, hashCode, buckets[index]); | 203 new _HashMapEntry(key, value, hashCode, buckets[index]); |
203 buckets[index] = entry; | 204 buckets[index] = entry; |
204 int newElements = _elementCount + 1; | 205 int newElements = _elementCount + 1; |
205 _elementCount = newElements; | 206 _elementCount = newElements; |
206 // If we end up with more than 75% non-empty entries, we | 207 // If we end up with more than 75% non-empty entries, we |
207 // resize the backing store. | 208 // resize the backing store. |
208 if ((newElements << 2) > ((length << 1) + length)) _resize(); | 209 if ((newElements << 2) > ((length << 1) + length)) _resize(); |
209 _modificationCount = (_modificationCount + 1) & _MODIFICATION_COUNT_MASK; | 210 _modificationCount = (_modificationCount + 1) & _MODIFICATION_COUNT_MASK; |
210 } | 211 } |
(...skipping 22 matching lines...) Expand all Loading... |
233 Set<K> _newKeySet() => new _HashSet<K>(); | 234 Set<K> _newKeySet() => new _HashSet<K>(); |
234 } | 235 } |
235 | 236 |
236 class _CustomHashMap<K, V> extends _HashMap<K, V> { | 237 class _CustomHashMap<K, V> extends _HashMap<K, V> { |
237 final _Equality<K> _equals; | 238 final _Equality<K> _equals; |
238 final _Hasher<K> _hashCode; | 239 final _Hasher<K> _hashCode; |
239 final _Predicate _validKey; | 240 final _Predicate _validKey; |
240 _CustomHashMap(this._equals, this._hashCode, validKey) | 241 _CustomHashMap(this._equals, this._hashCode, validKey) |
241 : _validKey = (validKey != null) ? validKey : new _TypeTest<K>().test; | 242 : _validKey = (validKey != null) ? validKey : new _TypeTest<K>().test; |
242 | 243 |
243 | |
244 bool containsKey(Object key) { | 244 bool containsKey(Object key) { |
245 if (!_validKey(key)) return false; | 245 if (!_validKey(key)) return false; |
246 int hashCode = _hashCode(key); | 246 int hashCode = _hashCode(key); |
247 List buckets = _buckets; | 247 List buckets = _buckets; |
248 int index = hashCode & (buckets.length - 1); | 248 int index = hashCode & (buckets.length - 1); |
249 _HashMapEntry entry = buckets[index]; | 249 _HashMapEntry entry = buckets[index]; |
250 while (entry != null) { | 250 while (entry != null) { |
251 if (hashCode == entry.hashCode && _equals(entry.key, key)) return true; | 251 if (hashCode == entry.hashCode && _equals(entry.key, key)) return true; |
252 entry = entry.next; | 252 entry = entry.next; |
253 } | 253 } |
254 return false; | 254 return false; |
255 } | 255 } |
256 | 256 |
257 V operator[](Object key) { | 257 V operator [](Object key) { |
258 if (!_validKey(key)) return null; | 258 if (!_validKey(key)) return null; |
259 int hashCode = _hashCode(key); | 259 int hashCode = _hashCode(key); |
260 List buckets = _buckets; | 260 List buckets = _buckets; |
261 int index = hashCode & (buckets.length - 1); | 261 int index = hashCode & (buckets.length - 1); |
262 _HashMapEntry entry = buckets[index]; | 262 _HashMapEntry entry = buckets[index]; |
263 while (entry != null) { | 263 while (entry != null) { |
264 if (hashCode == entry.hashCode && _equals(entry.key, key)) { | 264 if (hashCode == entry.hashCode && _equals(entry.key, key)) { |
265 return entry.value; | 265 return entry.value; |
266 } | 266 } |
267 entry = entry.next; | 267 entry = entry.next; |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
328 } | 328 } |
329 return null; | 329 return null; |
330 } | 330 } |
331 | 331 |
332 String toString() => Maps.mapToString(this); | 332 String toString() => Maps.mapToString(this); |
333 | 333 |
334 Set<K> _newKeySet() => new _CustomHashSet<K>(_equals, _hashCode, _validKey); | 334 Set<K> _newKeySet() => new _CustomHashSet<K>(_equals, _hashCode, _validKey); |
335 } | 335 } |
336 | 336 |
337 class _IdentityHashMap<K, V> extends _HashMap<K, V> { | 337 class _IdentityHashMap<K, V> extends _HashMap<K, V> { |
338 | |
339 bool containsKey(Object key) { | 338 bool containsKey(Object key) { |
340 int hashCode = identityHashCode(key); | 339 int hashCode = identityHashCode(key); |
341 List buckets = _buckets; | 340 List buckets = _buckets; |
342 int index = hashCode & (buckets.length - 1); | 341 int index = hashCode & (buckets.length - 1); |
343 _HashMapEntry entry = buckets[index]; | 342 _HashMapEntry entry = buckets[index]; |
344 while (entry != null) { | 343 while (entry != null) { |
345 if (hashCode == entry.hashCode && identical(entry.key, key)) return true; | 344 if (hashCode == entry.hashCode && identical(entry.key, key)) return true; |
346 entry = entry.next; | 345 entry = entry.next; |
347 } | 346 } |
348 return false; | 347 return false; |
349 } | 348 } |
350 | 349 |
351 V operator[](Object key) { | 350 V operator [](Object key) { |
352 int hashCode = identityHashCode(key); | 351 int hashCode = identityHashCode(key); |
353 List buckets = _buckets; | 352 List buckets = _buckets; |
354 int index = hashCode & (buckets.length - 1); | 353 int index = hashCode & (buckets.length - 1); |
355 _HashMapEntry entry = buckets[index]; | 354 _HashMapEntry entry = buckets[index]; |
356 while (entry != null) { | 355 while (entry != null) { |
357 if (hashCode == entry.hashCode && identical(entry.key, key)) { | 356 if (hashCode == entry.hashCode && identical(entry.key, key)) { |
358 return entry.value; | 357 return entry.value; |
359 } | 358 } |
360 entry = entry.next; | 359 entry = entry.next; |
361 } | 360 } |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
419 entry = next; | 418 entry = next; |
420 } | 419 } |
421 return null; | 420 return null; |
422 } | 421 } |
423 | 422 |
424 String toString() => Maps.mapToString(this); | 423 String toString() => Maps.mapToString(this); |
425 | 424 |
426 Set<K> _newKeySet() => new _IdentityHashSet<K>(); | 425 Set<K> _newKeySet() => new _IdentityHashSet<K>(); |
427 } | 426 } |
428 | 427 |
429 | |
430 class _HashMapEntry { | 428 class _HashMapEntry { |
431 final key; | 429 final key; |
432 var value; | 430 var value; |
433 final int hashCode; | 431 final int hashCode; |
434 _HashMapEntry next; | 432 _HashMapEntry next; |
435 _HashMapEntry(this.key, this.value, this.hashCode, this.next); | 433 _HashMapEntry(this.key, this.value, this.hashCode, this.next); |
436 } | 434 } |
437 | 435 |
438 abstract class _HashMapIterable<E> extends EfficientLengthIterable<E> { | 436 abstract class _HashMapIterable<E> extends EfficientLengthIterable<E> { |
439 final HashMap _map; | 437 final HashMap _map; |
440 _HashMapIterable(this._map); | 438 _HashMapIterable(this._map); |
441 int get length => _map.length; | 439 int get length => _map.length; |
442 bool get isEmpty => _map.isEmpty; | 440 bool get isEmpty => _map.isEmpty; |
443 bool get isNotEmpty => _map.isNotEmpty; | 441 bool get isNotEmpty => _map.isNotEmpty; |
444 } | 442 } |
445 | 443 |
446 class _HashMapKeyIterable<K> extends _HashMapIterable<K> { | 444 class _HashMapKeyIterable<K> extends _HashMapIterable<K> { |
447 _HashMapKeyIterable(HashMap map) : super(map); | 445 _HashMapKeyIterable(HashMap map) : super(map); |
448 Iterator<K> get iterator => new _HashMapKeyIterator<K>(_map); | 446 Iterator<K> get iterator => new _HashMapKeyIterator<K>(_map); |
449 bool contains(Object key) => _map.containsKey(key); | 447 bool contains(Object key) => _map.containsKey(key); |
450 void forEach(void action(K key)) { | 448 void forEach(void action(K key)) { |
451 _map.forEach((K key, _) { | 449 _map.forEach((K key, _) { |
452 action(key); | 450 action(key); |
453 }); | 451 }); |
454 } | 452 } |
| 453 |
455 Set<K> toSet() => _map._newKeySet()..addAll(this); | 454 Set<K> toSet() => _map._newKeySet()..addAll(this); |
456 } | 455 } |
457 | 456 |
458 class _HashMapValueIterable<V> extends _HashMapIterable<V> { | 457 class _HashMapValueIterable<V> extends _HashMapIterable<V> { |
459 _HashMapValueIterable(HashMap map) : super(map); | 458 _HashMapValueIterable(HashMap map) : super(map); |
460 Iterator<V> get iterator => new _HashMapValueIterator<V>(_map); | 459 Iterator<V> get iterator => new _HashMapValueIterator<V>(_map); |
461 bool contains(Object value) => _map.containsValue(value); | 460 bool contains(Object value) => _map.containsValue(value); |
462 void forEach(void action(V value)) { | 461 void forEach(void action(V value)) { |
463 _map.forEach((_, V value) { | 462 _map.forEach((_, V value) { |
464 action(value); | 463 action(value); |
465 }); | 464 }); |
466 } | 465 } |
467 } | 466 } |
468 | 467 |
469 abstract class _HashMapIterator<E> implements Iterator<E> { | 468 abstract class _HashMapIterator<E> implements Iterator<E> { |
470 final HashMap _map; | 469 final HashMap _map; |
471 final int _stamp; | 470 final int _stamp; |
472 | 471 |
473 int _index = 0; | 472 int _index = 0; |
474 _HashMapEntry _entry; | 473 _HashMapEntry _entry; |
475 | 474 |
476 _HashMapIterator(HashMap map) | 475 _HashMapIterator(HashMap map) |
477 : _map = map, _stamp = map._modificationCount; | 476 : _map = map, |
| 477 _stamp = map._modificationCount; |
478 | 478 |
479 bool moveNext() { | 479 bool moveNext() { |
480 if (_stamp != _map._modificationCount) { | 480 if (_stamp != _map._modificationCount) { |
481 throw new ConcurrentModificationError(_map); | 481 throw new ConcurrentModificationError(_map); |
482 } | 482 } |
483 _HashMapEntry entry = _entry; | 483 _HashMapEntry entry = _entry; |
484 if (entry != null) { | 484 if (entry != null) { |
485 _HashMapEntry next = entry.next; | 485 _HashMapEntry next = entry.next; |
486 if (next != null) { | 486 if (next != null) { |
487 _entry = next; | 487 _entry = next; |
(...skipping 25 matching lines...) Expand all Loading... |
513 } | 513 } |
514 | 514 |
515 class _HashMapValueIterator<V> extends _HashMapIterator<V> { | 515 class _HashMapValueIterator<V> extends _HashMapIterator<V> { |
516 _HashMapValueIterator(HashMap map) : super(map); | 516 _HashMapValueIterator(HashMap map) : super(map); |
517 V get current { | 517 V get current { |
518 _HashMapEntry entry = _entry; | 518 _HashMapEntry entry = _entry; |
519 return (entry == null) ? null : entry.value; | 519 return (entry == null) ? null : entry.value; |
520 } | 520 } |
521 } | 521 } |
522 | 522 |
523 @patch class HashSet<E> { | 523 @patch |
524 @patch factory HashSet({ bool equals(E e1, E e2), | 524 class HashSet<E> { |
525 int hashCode(E e), | 525 @patch |
526 bool isValidKey(potentialKey) }) { | 526 factory HashSet( |
| 527 {bool equals(E e1, E e2), |
| 528 int hashCode(E e), |
| 529 bool isValidKey(potentialKey)}) { |
527 if (isValidKey == null) { | 530 if (isValidKey == null) { |
528 if (hashCode == null) { | 531 if (hashCode == null) { |
529 if (equals == null) { | 532 if (equals == null) { |
530 return new _HashSet<E>(); | 533 return new _HashSet<E>(); |
531 } | 534 } |
532 hashCode = _defaultHashCode; | 535 hashCode = _defaultHashCode; |
533 } else { | 536 } else { |
534 if (identical(identityHashCode, hashCode) && | 537 if (identical(identityHashCode, hashCode) && |
535 identical(identical, equals)) { | 538 identical(identical, equals)) { |
536 return new _IdentityHashSet<E>(); | 539 return new _IdentityHashSet<E>(); |
537 } | 540 } |
538 if (equals == null) { | 541 if (equals == null) { |
539 equals = _defaultEquals; | 542 equals = _defaultEquals; |
540 } | 543 } |
541 } | 544 } |
542 } else { | 545 } else { |
543 if (hashCode == null) { | 546 if (hashCode == null) { |
544 hashCode = _defaultHashCode; | 547 hashCode = _defaultHashCode; |
545 } | 548 } |
546 if (equals == null) { | 549 if (equals == null) { |
547 equals = _defaultEquals; | 550 equals = _defaultEquals; |
548 } | 551 } |
549 } | 552 } |
550 return new _CustomHashSet<E>(equals, hashCode, isValidKey); | 553 return new _CustomHashSet<E>(equals, hashCode, isValidKey); |
551 } | 554 } |
552 | 555 |
553 @patch factory HashSet.identity() = _IdentityHashSet<E>; | 556 @patch |
| 557 factory HashSet.identity() = _IdentityHashSet<E>; |
554 } | 558 } |
555 | 559 |
556 class _HashSet<E> extends _HashSetBase<E> implements HashSet<E> { | 560 class _HashSet<E> extends _HashSetBase<E> implements HashSet<E> { |
557 static const int _INITIAL_CAPACITY = 8; | 561 static const int _INITIAL_CAPACITY = 8; |
558 | 562 |
559 List<_HashSetEntry> _buckets = new List(_INITIAL_CAPACITY); | 563 List<_HashSetEntry> _buckets = new List(_INITIAL_CAPACITY); |
560 int _elementCount = 0; | 564 int _elementCount = 0; |
561 int _modificationCount = 0; | 565 int _modificationCount = 0; |
562 | 566 |
563 bool _equals(e1, e2) => e1 == e2; | 567 bool _equals(e1, e2) => e1 == e2; |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
642 bool remove(Object object) => _remove(object, _hashCode(object)); | 646 bool remove(Object object) => _remove(object, _hashCode(object)); |
643 | 647 |
644 void removeAll(Iterable<Object> objectsToRemove) { | 648 void removeAll(Iterable<Object> objectsToRemove) { |
645 for (Object object in objectsToRemove) { | 649 for (Object object in objectsToRemove) { |
646 _remove(object, _hashCode(object)); | 650 _remove(object, _hashCode(object)); |
647 } | 651 } |
648 } | 652 } |
649 | 653 |
650 void _filterWhere(bool test(E element), bool removeMatching) { | 654 void _filterWhere(bool test(E element), bool removeMatching) { |
651 int length = _buckets.length; | 655 int length = _buckets.length; |
652 for (int index = 0; index < length; index++) { | 656 for (int index = 0; index < length; index++) { |
653 _HashSetEntry entry = _buckets[index]; | 657 _HashSetEntry entry = _buckets[index]; |
654 _HashSetEntry previous = null; | 658 _HashSetEntry previous = null; |
655 while (entry != null) { | 659 while (entry != null) { |
656 int modificationCount = _modificationCount; | 660 int modificationCount = _modificationCount; |
657 bool testResult = test(entry.key); | 661 bool testResult = test(entry.key); |
658 if (modificationCount != _modificationCount) { | 662 if (modificationCount != _modificationCount) { |
659 throw new ConcurrentModificationError(this); | 663 throw new ConcurrentModificationError(this); |
660 } | 664 } |
661 if (testResult == removeMatching) { | 665 if (testResult == removeMatching) { |
662 _HashSetEntry next = entry.remove(); | 666 _HashSetEntry next = entry.remove(); |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
788 } | 792 } |
789 | 793 |
790 class _HashSetIterator<E> implements Iterator<E> { | 794 class _HashSetIterator<E> implements Iterator<E> { |
791 final _HashSet _set; | 795 final _HashSet _set; |
792 final int _modificationCount; | 796 final int _modificationCount; |
793 int _index = 0; | 797 int _index = 0; |
794 _HashSetEntry _next; | 798 _HashSetEntry _next; |
795 E _current; | 799 E _current; |
796 | 800 |
797 _HashSetIterator(_HashSet hashSet) | 801 _HashSetIterator(_HashSet hashSet) |
798 : _set = hashSet, _modificationCount = hashSet._modificationCount; | 802 : _set = hashSet, |
| 803 _modificationCount = hashSet._modificationCount; |
799 | 804 |
800 bool moveNext() { | 805 bool moveNext() { |
801 if (_modificationCount != _set._modificationCount) { | 806 if (_modificationCount != _set._modificationCount) { |
802 throw new ConcurrentModificationError(_set); | 807 throw new ConcurrentModificationError(_set); |
803 } | 808 } |
804 if (_next != null) { | 809 if (_next != null) { |
805 _current = _next.key; | 810 _current = _next.key; |
806 _next = _next.next; | 811 _next = _next.next; |
807 return true; | 812 return true; |
808 } | 813 } |
(...skipping 14 matching lines...) Expand all Loading... |
823 E get current => _current; | 828 E get current => _current; |
824 } | 829 } |
825 | 830 |
826 class _LinkedHashMapEntry extends _HashMapEntry { | 831 class _LinkedHashMapEntry extends _HashMapEntry { |
827 /// Double-linked list of entries of a linked hash map. | 832 /// Double-linked list of entries of a linked hash map. |
828 /// The _LinkedHashMap itself is the head of the list, so the type is "var". | 833 /// The _LinkedHashMap itself is the head of the list, so the type is "var". |
829 /// Both are initialized to `this` when initialized. | 834 /// Both are initialized to `this` when initialized. |
830 var _nextEntry; | 835 var _nextEntry; |
831 var _previousEntry; | 836 var _previousEntry; |
832 _LinkedHashMapEntry(key, value, int hashCode, _LinkedHashMapEntry next, | 837 _LinkedHashMapEntry(key, value, int hashCode, _LinkedHashMapEntry next, |
833 this._previousEntry, this._nextEntry) | 838 this._previousEntry, this._nextEntry) |
834 : super(key, value, hashCode, next) { | 839 : super(key, value, hashCode, next) { |
835 _previousEntry._nextEntry = this; | 840 _previousEntry._nextEntry = this; |
836 _nextEntry._previousEntry = this; | 841 _nextEntry._previousEntry = this; |
837 } | 842 } |
838 } | 843 } |
839 | 844 |
840 class _LinkedHashMapKeyIterable<K> extends EfficientLengthIterable<K> { | 845 class _LinkedHashMapKeyIterable<K> extends EfficientLengthIterable<K> { |
841 LinkedHashMap<K, dynamic> _map; | 846 LinkedHashMap<K, dynamic> _map; |
842 _LinkedHashMapKeyIterable(this._map); | 847 _LinkedHashMapKeyIterable(this._map); |
843 Iterator<K> get iterator => new _LinkedHashMapKeyIterator<K>(_map); | 848 Iterator<K> get iterator => new _LinkedHashMapKeyIterator<K>(_map); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
890 class _LinkedHashMapKeyIterator<K> extends _LinkedHashMapIterator<K> { | 895 class _LinkedHashMapKeyIterator<K> extends _LinkedHashMapIterator<K> { |
891 _LinkedHashMapKeyIterator(LinkedHashMap map) : super(map); | 896 _LinkedHashMapKeyIterator(LinkedHashMap map) : super(map); |
892 K _getValue(_LinkedHashMapEntry entry) => entry.key; | 897 K _getValue(_LinkedHashMapEntry entry) => entry.key; |
893 } | 898 } |
894 | 899 |
895 class _LinkedHashMapValueIterator<V> extends _LinkedHashMapIterator<V> { | 900 class _LinkedHashMapValueIterator<V> extends _LinkedHashMapIterator<V> { |
896 _LinkedHashMapValueIterator(LinkedHashMap map) : super(map); | 901 _LinkedHashMapValueIterator(LinkedHashMap map) : super(map); |
897 V _getValue(_LinkedHashMapEntry entry) => entry.value; | 902 V _getValue(_LinkedHashMapEntry entry) => entry.value; |
898 } | 903 } |
899 | 904 |
900 | |
901 /** | 905 /** |
902 * A hash-based map that iterates keys and values in key insertion order. | 906 * A hash-based map that iterates keys and values in key insertion order. |
903 */ | 907 */ |
904 @patch class LinkedHashMap<K, V> { | 908 @patch |
| 909 class LinkedHashMap<K, V> { |
905 /// Holds a double-linked list of entries in insertion order. | 910 /// Holds a double-linked list of entries in insertion order. |
906 /// The fields have the same name as the ones in [_LinkedHashMapEntry], | 911 /// The fields have the same name as the ones in [_LinkedHashMapEntry], |
907 /// and this map is itself used as the head entry of the list. | 912 /// and this map is itself used as the head entry of the list. |
908 /// Set to `this` when initialized, representing the empty list (containing | 913 /// Set to `this` when initialized, representing the empty list (containing |
909 /// only the head entry itself). | 914 /// only the head entry itself). |
910 var _nextEntry; | 915 var _nextEntry; |
911 var _previousEntry; | 916 var _previousEntry; |
912 | 917 |
913 @patch factory LinkedHashMap({ bool equals(K key1, K key2), | 918 @patch |
914 int hashCode(K key), | 919 factory LinkedHashMap( |
915 bool isValidKey(potentialKey) }) { | 920 {bool equals(K key1, K key2), |
| 921 int hashCode(K key), |
| 922 bool isValidKey(potentialKey)}) { |
916 if (isValidKey == null) { | 923 if (isValidKey == null) { |
917 if (hashCode == null) { | 924 if (hashCode == null) { |
918 if (equals == null) { | 925 if (equals == null) { |
919 return new _InternalLinkedHashMap<K, V>(); | 926 return new _InternalLinkedHashMap<K, V>(); |
920 } | 927 } |
921 hashCode = _defaultHashCode; | 928 hashCode = _defaultHashCode; |
922 } else { | 929 } else { |
923 if (identical(identityHashCode, hashCode) && | 930 if (identical(identityHashCode, hashCode) && |
924 identical(identical, equals)) { | 931 identical(identical, equals)) { |
925 return new _CompactLinkedIdentityHashMap<K, V>(); | 932 return new _CompactLinkedIdentityHashMap<K, V>(); |
926 } | 933 } |
927 if (equals == null) { | 934 if (equals == null) { |
928 equals = _defaultEquals; | 935 equals = _defaultEquals; |
929 } | 936 } |
930 } | 937 } |
931 } else { | 938 } else { |
932 if (hashCode == null) { | 939 if (hashCode == null) { |
933 hashCode = _defaultHashCode; | 940 hashCode = _defaultHashCode; |
934 } | 941 } |
935 if (equals == null) { | 942 if (equals == null) { |
936 equals = _defaultEquals; | 943 equals = _defaultEquals; |
937 } | 944 } |
938 } | 945 } |
939 return new _CompactLinkedCustomHashMap<K, V>(equals, hashCode, isValidKey); | 946 return new _CompactLinkedCustomHashMap<K, V>(equals, hashCode, isValidKey); |
940 } | 947 } |
941 | 948 |
942 @patch factory LinkedHashMap.identity() = | 949 @patch |
943 _CompactLinkedIdentityHashMap<K, V>; | 950 factory LinkedHashMap.identity() = _CompactLinkedIdentityHashMap<K, V>; |
944 } | 951 } |
945 | 952 |
946 @patch class LinkedHashSet<E> { | 953 @patch |
947 @patch factory LinkedHashSet({ bool equals(E e1, E e2), | 954 class LinkedHashSet<E> { |
948 int hashCode(E e), | 955 @patch |
949 bool isValidKey(potentialKey) }) { | 956 factory LinkedHashSet( |
| 957 {bool equals(E e1, E e2), |
| 958 int hashCode(E e), |
| 959 bool isValidKey(potentialKey)}) { |
950 if (isValidKey == null) { | 960 if (isValidKey == null) { |
951 if (hashCode == null) { | 961 if (hashCode == null) { |
952 if (equals == null) { | 962 if (equals == null) { |
953 return new _CompactLinkedHashSet<E>(); | 963 return new _CompactLinkedHashSet<E>(); |
954 } | 964 } |
955 hashCode = _defaultHashCode; | 965 hashCode = _defaultHashCode; |
956 } else { | 966 } else { |
957 if (identical(identityHashCode, hashCode) && | 967 if (identical(identityHashCode, hashCode) && |
958 identical(identical, equals)) { | 968 identical(identical, equals)) { |
959 return new _CompactLinkedIdentityHashSet<E>(); | 969 return new _CompactLinkedIdentityHashSet<E>(); |
960 } | 970 } |
961 if (equals == null) { | 971 if (equals == null) { |
962 equals = _defaultEquals; | 972 equals = _defaultEquals; |
963 } | 973 } |
964 } | 974 } |
965 } else { | 975 } else { |
966 if (hashCode == null) { | 976 if (hashCode == null) { |
967 hashCode = _defaultHashCode; | 977 hashCode = _defaultHashCode; |
968 } | 978 } |
969 if (equals == null) { | 979 if (equals == null) { |
970 equals = _defaultEquals; | 980 equals = _defaultEquals; |
971 } | 981 } |
972 } | 982 } |
973 return new _CompactLinkedCustomHashSet<E>(equals, hashCode, isValidKey); | 983 return new _CompactLinkedCustomHashSet<E>(equals, hashCode, isValidKey); |
974 } | 984 } |
975 | 985 |
976 @patch factory LinkedHashSet.identity() = | 986 @patch |
977 _CompactLinkedIdentityHashSet<E>; | 987 factory LinkedHashSet.identity() = _CompactLinkedIdentityHashSet<E>; |
978 } | 988 } |
OLD | NEW |