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

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

Issue 23494027: Make LinkedHashMap also have a factory constructor and be customizable (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Address comments. 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), 6 /* patch */ factory HashMap({ bool equals(K key1, K key2),
7 int hashCode(K key) }) { 7 int hashCode(K key),
8 if (hashCode == null) { 8 bool isValidKey(potentialKey) }) {
9 if (isValidKey == null) {
10 if (hashCode == null) {
11 if (equals == null) {
12 return new _HashMap<K, V>();
13 }
14 if (identical(identical, equals)) {
15 return new _IdentityHashMap<K, V>();
16 }
17 hashCode = _defaultHashCode;
18 } else if (equals == null) {
19 equals = _defaultEquals;
20 }
21 } else {
22 if (hashCode == null) {
23 hashCode = _defaultHashCode;
24 }
9 if (equals == null) { 25 if (equals == null) {
10 return new _HashMapImpl<K, V>(); 26 equals = _defaultEquals;
11 } 27 }
12 if (identical(identical, equals)) {
13 return new _IdentityHashMap<K, V>();
14 }
15 hashCode = _defaultHashCode;
16 } else if (equals == null) {
17 equals = _defaultEquals;
18 } 28 }
19 return new _CustomHashMap<K, V>(equals, hashCode); 29 return new _CustomHashMap<K, V>(equals, hashCode, isValidKey);
20 } 30 }
21 } 31 }
22 32
23 const int _MODIFICATION_COUNT_MASK = 0x3fffffff; 33 const int _MODIFICATION_COUNT_MASK = 0x3fffffff;
24 34
25 class _HashMapImpl<K, V> implements HashMap<K, V> { 35 class _HashMap<K, V> implements HashMap<K, V> {
26 static const int _INITIAL_CAPACITY = 8; 36 static const int _INITIAL_CAPACITY = 8;
27 37
28 int _elementCount = 0; 38 int _elementCount = 0;
29 List<_HashMapEntry> _buckets = new List(_INITIAL_CAPACITY); 39 List<_HashMapEntry> _buckets = new List(_INITIAL_CAPACITY);
30 int _modificationCount = 0; 40 int _modificationCount = 0;
31 41
32 int get length => _elementCount; 42 int get length => _elementCount;
33 bool get isEmpty => _elementCount == 0; 43 bool get isEmpty => _elementCount == 0;
34 bool get isNotEmpty => _elementCount != 0; 44 bool get isNotEmpty => _elementCount != 0;
35 45
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
137 147
138 V remove(Object key) { 148 V remove(Object key) {
139 int hashCode = key.hashCode; 149 int hashCode = key.hashCode;
140 List buckets = _buckets; 150 List buckets = _buckets;
141 int index = hashCode & (buckets.length - 1); 151 int index = hashCode & (buckets.length - 1);
142 _HashMapEntry entry = buckets[index]; 152 _HashMapEntry entry = buckets[index];
143 _HashMapEntry previous = null; 153 _HashMapEntry previous = null;
144 while (entry != null) { 154 while (entry != null) {
145 _HashMapEntry next = entry.next; 155 _HashMapEntry next = entry.next;
146 if (hashCode == entry.hashCode && entry.key == key) { 156 if (hashCode == entry.hashCode && entry.key == key) {
147 if (previous == null) { 157 _removeEntry(entry, previous, index);
148 buckets[index] = next;
149 } else {
150 previous.next = next;
151 }
152 _elementCount--; 158 _elementCount--;
153 _modificationCount = 159 _modificationCount =
154 (_modificationCount + 1) & _MODIFICATION_COUNT_MASK; 160 (_modificationCount + 1) & _MODIFICATION_COUNT_MASK;
155 return entry.value; 161 return entry.value;
156 } 162 }
157 previous = entry; 163 previous = entry;
158 entry = next; 164 entry = next;
159 } 165 }
160 return null; 166 return null;
161 } 167 }
162 168
163 void clear() { 169 void clear() {
164 _elementCount = 0; 170 _elementCount = 0;
165 _buckets = new List(_INITIAL_CAPACITY); 171 _buckets = new List(_INITIAL_CAPACITY);
166 _modificationCount = (_modificationCount + 1) & _MODIFICATION_COUNT_MASK; 172 _modificationCount = (_modificationCount + 1) & _MODIFICATION_COUNT_MASK;
167 } 173 }
168 174
175 void _removeEntry(_HashMapEntry entry,
176 _HashMapEntry previousInBucket,
177 int bucketIndex) {
178 if (previousInBucket == null) {
179 _buckets[bucketIndex] = entry.next;
180 } else {
181 previousInBucket.next = entry.next;
182 }
183 }
184
169 void _addEntry(List buckets, int index, int length, 185 void _addEntry(List buckets, int index, int length,
170 K key, V value, int hashCode) { 186 K key, V value, int hashCode) {
171 _HashMapEntry entry = 187 _HashMapEntry entry =
172 new _HashMapEntry(key, value, hashCode, buckets[index]); 188 new _HashMapEntry(key, value, hashCode, buckets[index]);
173 buckets[index] = entry; 189 buckets[index] = entry;
174 int newElements = _elementCount + 1; 190 int newElements = _elementCount + 1;
175 _elementCount = newElements; 191 _elementCount = newElements;
176 // If we end up with more than 75% non-empty entries, we 192 // If we end up with more than 75% non-empty entries, we
177 // resize the backing store. 193 // resize the backing store.
178 if ((newElements << 2) > ((length << 1) + length)) _resize(); 194 if ((newElements << 2) > ((length << 1) + length)) _resize();
(...skipping 15 matching lines...) Expand all
194 newBuckets[index] = entry; 210 newBuckets[index] = entry;
195 entry = next; 211 entry = next;
196 } 212 }
197 } 213 }
198 _buckets = newBuckets; 214 _buckets = newBuckets;
199 } 215 }
200 216
201 String toString() => Maps.mapToString(this); 217 String toString() => Maps.mapToString(this);
202 } 218 }
203 219
204 class _CustomHashMap<K, V> extends _HashMapImpl<K, V> { 220 class _CustomHashMap<K, V> extends _HashMap<K, V> {
205 final _Equality<K> _equals; 221 final _Equality<K> _equals;
206 final _Hasher<K> _hashCode; 222 final _Hasher<K> _hashCode;
207 _CustomHashMap(this._equals, this._hashCode); 223 final _Predicate _validKey;
224 _CustomHashMap(this._equals, this._hashCode, validKey)
225 : _validKey = (validKey != null) ? validKey : new _TypeTest<K>().test;
208 226
209 bool containsKey(Object key) { 227 bool containsKey(Object key) {
228 if (!_validKey(key)) return false;
210 int hashCode = _hashCode(key); 229 int hashCode = _hashCode(key);
211 List buckets = _buckets; 230 List buckets = _buckets;
212 int index = hashCode & (buckets.length - 1); 231 int index = hashCode & (buckets.length - 1);
213 _HashMapEntry entry = buckets[index]; 232 _HashMapEntry entry = buckets[index];
214 while (entry != null) { 233 while (entry != null) {
215 if (hashCode == entry.hashCode && _equals(entry.key, key)) return true; 234 if (hashCode == entry.hashCode && _equals(entry.key, key)) return true;
216 entry = entry.next; 235 entry = entry.next;
217 } 236 }
218 return false; 237 return false;
219 } 238 }
220 239
221 V operator[](Object key) { 240 V operator[](Object key) {
241 if (!_validKey(key)) return null;
222 int hashCode = _hashCode(key); 242 int hashCode = _hashCode(key);
223 List buckets = _buckets; 243 List buckets = _buckets;
224 int index = hashCode & (buckets.length - 1); 244 int index = hashCode & (buckets.length - 1);
225 _HashMapEntry entry = buckets[index]; 245 _HashMapEntry entry = buckets[index];
226 while (entry != null) { 246 while (entry != null) {
227 if (hashCode == entry.hashCode && _equals(entry.key, key)) { 247 if (hashCode == entry.hashCode && _equals(entry.key, key)) {
228 return entry.value; 248 return entry.value;
229 } 249 }
230 entry = entry.next; 250 entry = entry.next;
231 } 251 }
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
264 V value = ifAbsent(); 284 V value = ifAbsent();
265 if (stamp == _modificationCount) { 285 if (stamp == _modificationCount) {
266 _addEntry(buckets, index, length, key, value, hashCode); 286 _addEntry(buckets, index, length, key, value, hashCode);
267 } else { 287 } else {
268 this[key] = value; 288 this[key] = value;
269 } 289 }
270 return value; 290 return value;
271 } 291 }
272 292
273 V remove(Object key) { 293 V remove(Object key) {
294 if (!_validKey(key)) return null;
274 int hashCode = _hashCode(key); 295 int hashCode = _hashCode(key);
275 List buckets = _buckets; 296 List buckets = _buckets;
276 int index = hashCode & (buckets.length - 1); 297 int index = hashCode & (buckets.length - 1);
277 _HashMapEntry entry = buckets[index]; 298 _HashMapEntry entry = buckets[index];
278 _HashMapEntry previous = null; 299 _HashMapEntry previous = null;
279 while (entry != null) { 300 while (entry != null) {
280 _HashMapEntry next = entry.next; 301 _HashMapEntry next = entry.next;
281 if (hashCode == entry.hashCode && _equals(entry.key, key)) { 302 if (hashCode == entry.hashCode && _equals(entry.key, key)) {
282 if (previous == null) { 303 _removeEntry(entry, previous, index);
283 buckets[index] = next;
284 } else {
285 previous.next = next;
286 }
287 _elementCount--; 304 _elementCount--;
288 _modificationCount = 305 _modificationCount =
289 (_modificationCount + 1) & _MODIFICATION_COUNT_MASK; 306 (_modificationCount + 1) & _MODIFICATION_COUNT_MASK;
290 return entry.value; 307 return entry.value;
291 } 308 }
292 previous = entry; 309 previous = entry;
293 entry = next; 310 entry = next;
294 } 311 }
295 return null; 312 return null;
296 } 313 }
297 314
298 String toString() => Maps.mapToString(this); 315 String toString() => Maps.mapToString(this);
299 } 316 }
300 317
301 class _IdentityHashMap<K, V> extends _HashMapImpl<K, V> { 318 class _IdentityHashMap<K, V> extends _HashMap<K, V> {
302 bool containsKey(Object key) { 319 bool containsKey(Object key) {
303 int hashCode = key.hashCode; 320 int hashCode = key.hashCode;
304 List buckets = _buckets; 321 List buckets = _buckets;
305 int index = hashCode & (buckets.length - 1); 322 int index = hashCode & (buckets.length - 1);
306 _HashMapEntry entry = buckets[index]; 323 _HashMapEntry entry = buckets[index];
307 while (entry != null) { 324 while (entry != null) {
308 if (hashCode == entry.hashCode && identical(entry.key, key)) return true; 325 if (hashCode == entry.hashCode && identical(entry.key, key)) return true;
309 entry = entry.next; 326 entry = entry.next;
310 } 327 }
311 return false; 328 return false;
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
365 382
366 V remove(Object key) { 383 V remove(Object key) {
367 int hashCode = key.hashCode; 384 int hashCode = key.hashCode;
368 List buckets = _buckets; 385 List buckets = _buckets;
369 int index = hashCode & (buckets.length - 1); 386 int index = hashCode & (buckets.length - 1);
370 _HashMapEntry entry = buckets[index]; 387 _HashMapEntry entry = buckets[index];
371 _HashMapEntry previous = null; 388 _HashMapEntry previous = null;
372 while (entry != null) { 389 while (entry != null) {
373 _HashMapEntry next = entry.next; 390 _HashMapEntry next = entry.next;
374 if (hashCode == entry.hashCode && identical(entry.key, key)) { 391 if (hashCode == entry.hashCode && identical(entry.key, key)) {
375 if (previous == null) { 392 _removeEntry(entry, previous, index);
376 buckets[index] = next;
377 } else {
378 previous.next = next;
379 }
380 _elementCount--; 393 _elementCount--;
381 _modificationCount = 394 _modificationCount =
382 (_modificationCount + 1) & _MODIFICATION_COUNT_MASK; 395 (_modificationCount + 1) & _MODIFICATION_COUNT_MASK;
383 return entry.value; 396 return entry.value;
384 } 397 }
385 previous = entry; 398 previous = entry;
386 entry = next; 399 entry = next;
387 } 400 }
388 return null; 401 return null;
389 } 402 }
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after
589 LinkedHashMap<dynamic, V> _map; 602 LinkedHashMap<dynamic, V> _map;
590 _LinkedHashMapValueIterable(this._map); 603 _LinkedHashMapValueIterable(this._map);
591 Iterator<K> get iterator => new _LinkedHashMapValueIterator<V>(_map); 604 Iterator<K> get iterator => new _LinkedHashMapValueIterator<V>(_map);
592 bool contains(V value) => _map.containsValue(value); 605 bool contains(V value) => _map.containsValue(value);
593 bool get isEmpty => _map.isEmpty; 606 bool get isEmpty => _map.isEmpty;
594 bool get isNotEmpty => _map.isNotEmpty; 607 bool get isNotEmpty => _map.isNotEmpty;
595 int get length => _map.length; 608 int get length => _map.length;
596 } 609 }
597 610
598 abstract class _LinkedHashMapIterator<T> implements Iterator<T> { 611 abstract class _LinkedHashMapIterator<T> implements Iterator<T> {
599 final _LinkedHashMap _map; 612 final LinkedHashMap _map;
600 var _next; 613 var _next;
601 T _current; 614 T _current;
602 int _modificationCount; 615 int _modificationCount;
603 _LinkedHashMapIterator(_LinkedHashMap map) 616 _LinkedHashMapIterator(LinkedHashMap map)
604 : _map = map, 617 : _map = map,
605 _current = null, 618 _current = null,
606 _next = map._nextEntry, 619 _next = map._nextEntry,
607 _modificationCount = map._modificationCount; 620 _modificationCount = map._modificationCount;
608 621
609 bool moveNext() { 622 bool moveNext() {
610 if (_modificationCount != _map._modificationCount) { 623 if (_modificationCount != _map._modificationCount) {
611 throw new ConcurrentModificationError(_map); 624 throw new ConcurrentModificationError(_map);
612 } 625 }
613 if (identical(_map, _next)) { 626 if (identical(_map, _next)) {
614 _current = null; 627 _current = null;
615 return false; 628 return false;
616 } 629 }
617 _LinkedHashMapEntry entry = _next; 630 _LinkedHashMapEntry entry = _next;
618 _next = entry._nextEntry; 631 _next = entry._nextEntry;
619 _current = _getValue(entry); 632 _current = _getValue(entry);
620 return true; 633 return true;
621 } 634 }
622 635
623 T _getValue(_LinkedHashMapEntry entry); 636 T _getValue(_LinkedHashMapEntry entry);
624 637
625 T get current => _current; 638 T get current => _current;
626 } 639 }
627 640
628 class _LinkedHashMapKeyIterator<K> extends _LinkedHashMapIterator<K> { 641 class _LinkedHashMapKeyIterator<K> extends _LinkedHashMapIterator<K> {
629 _LinkedHashMapKeyIterator(_LinkedHashMap map) : super(map); 642 _LinkedHashMapKeyIterator(LinkedHashMap map) : super(map);
630 K _getValue(_LinkedHashMapEntry entry) => entry.key; 643 K _getValue(_LinkedHashMapEntry entry) => entry.key;
631 } 644 }
632 645
633 class _LinkedHashMapValueIterator<V> extends _LinkedHashMapIterator<V> { 646 class _LinkedHashMapValueIterator<V> extends _LinkedHashMapIterator<V> {
634 _LinkedHashMapValueIterator(_LinkedHashMap map) : super(map); 647 _LinkedHashMapValueIterator(LinkedHashMap map) : super(map);
635 V _getValue(_LinkedHashMapEntry entry) => entry.value; 648 V _getValue(_LinkedHashMapEntry entry) => entry.value;
636 } 649 }
637 650
638 651
639 /** 652 /**
640 * A hash-based map that iterates keys and values in key insertion order. 653 * A hash-based map that iterates keys and values in key insertion order.
641 */ 654 */
642 patch class LinkedHashMap<K, V> { 655 patch class LinkedHashMap<K, V> {
643 static const int _INITIAL_CAPACITY = 8;
644 static const int _MODIFICATION_COUNT_MASK = 0x3fffffff;
645
646 int _elementCount = 0;
647 List<_HashMapEntry> _buckets = new List(_INITIAL_CAPACITY);
648 int _modificationCount = 0;
649
650 var _nextEntry; 656 var _nextEntry;
651 var _previousEntry; 657 var _previousEntry;
652 658
653 /* patch */ LinkedHashMap() { 659 /* patch */ factory LinkedHashMap({ bool equals(K key1, K key2),
654 _nextEntry = _previousEntry = this; 660 int hashCode(K key),
661 bool isValidKey(potentialKey) }) {
662 if (isValidKey == null) {
663 if (hashCode == null) {
664 if (equals == null) {
665 return new _LinkedHashMap<K, V>();
666 }
667 if (identical(identical, equals)) {
668 return new _LinkedIdentityHashMap<K, V>();
669 }
670 hashCode = _defaultHashCode;
671 } else if (equals == null) {
672 equals = _defaultEquals;
673 }
674 } else {
675 if (hashCode == null) {
676 hashCode = _defaultHashCode;
677 }
678 if (equals == null) {
679 equals = _defaultEquals;
680 }
681 }
682 return new _LinkedCustomHashMap<K, V>(equals, hashCode, isValidKey);
655 } 683 }
684 }
656 685
657 /* patch */ int get length => _elementCount; 686 // Methods that are exactly the same in all three linked hash map variants.
658 /* patch */ bool get isEmpty => _elementCount == 0; 687 abstract class _LinkedHashMapMixin<K, V> implements LinkedHashMap<K, V> {
659 /* patch */ bool get isNotEmpty => _elementCount != 0; 688 var _nextEntry;
689 var _previousEntry;
660 690
661 /* patch */ Iterable<K> get keys => new _LinkedHashMapKeyIterable<K>(this); 691 bool containsValue(Object value) {
662 /* patch */ Iterable<V> get values => new _LinkedHashMapValueIterable<V>(this) ; 692 int modificationCount = _modificationCount;
663
664 /* patch */ bool containsKey(Object key) {
665 int hashCode = key.hashCode;
666 List buckets = _buckets;
667 int index = hashCode & (buckets.length - 1);
668 _HashMapEntry entry = buckets[index];
669 while (entry != null) {
670 if (hashCode == entry.hashCode && entry.key == key) return true;
671 entry = entry.next;
672 }
673 return false;
674 }
675
676 /* patch */ bool containsValue(Object value) {
677 var cursor = _nextEntry; 693 var cursor = _nextEntry;
678 int modificationCount = _modificationCount;
679 while (!identical(cursor, this)) { 694 while (!identical(cursor, this)) {
680 _HashMapEntry entry = cursor; 695 _HashMapEntry entry = cursor;
681 if (entry.value == value) return true; 696 if (entry.value == value) return true;
697 if (modificationCount != _modificationCount) {
698 throw new ConcurrentModificationError(this);
699 }
682 cursor = cursor._nextEntry; 700 cursor = cursor._nextEntry;
683 } 701 }
684 return false; 702 return false;
685 } 703 }
686 704
687 /* patch */ V operator[](Object key) { 705 void forEach(void action(K key, V value)) {
688 int hashCode = key.hashCode; 706 int modificationCount = _modificationCount;
689 List buckets = _buckets;
690 int index = hashCode & (buckets.length - 1);
691 _HashMapEntry entry = buckets[index];
692 while (entry != null) {
693 if (hashCode == entry.hashCode && entry.key == key) {
694 return entry.value;
695 }
696 entry = entry.next;
697 }
698 return null;
699 }
700
701 /* patch */ void operator []=(K key, V value) {
702 int hashCode = key.hashCode;
703 List buckets = _buckets;
704 int length = buckets.length;
705 int index = hashCode & (length - 1);
706 _HashMapEntry entry = buckets[index];
707 while (entry != null) {
708 if (hashCode == entry.hashCode && entry.key == key) {
709 entry.value = value;
710 return;
711 }
712 entry = entry.next;
713 }
714 _addEntry(buckets, index, length, key, value, hashCode);
715 }
716
717 /* patch */ V putIfAbsent(K key, V ifAbsent()) {
718 int hashCode = key.hashCode;
719 List buckets = _buckets;
720 int length = buckets.length;
721 int index = hashCode & (length - 1);
722 _HashMapEntry entry = buckets[index];
723 while (entry != null) {
724 if (hashCode == entry.hashCode && entry.key == key) {
725 return entry.value;
726 }
727 entry = entry.next;
728 }
729 int stamp = _modificationCount;
730 V value = ifAbsent();
731 if (stamp == _modificationCount) {
732 _addEntry(buckets, index, length, key, value, hashCode);
733 } else {
734 this[key] = value;
735 }
736 return value;
737 }
738
739 /* patch */ void addAll(Map<K, V> other) {
740 other.forEach((K key, V value) {
741 this[key] = value;
742 });
743 }
744
745 /* patch */ void forEach(void action(K key, V value)) {
746 int stamp = _modificationCount;
747 var cursor = _nextEntry; 707 var cursor = _nextEntry;
748 while (!identical(cursor, this)) { 708 while (!identical(cursor, this)) {
749 _HashMapEntry entry = cursor; 709 _HashMapEntry entry = cursor;
750 action(entry.key, entry.value); 710 action(entry.key, entry.value);
751 if (stamp != _modificationCount) { 711 if (modificationCount != _modificationCount) {
752 throw new ConcurrentModificationError(this); 712 throw new ConcurrentModificationError(this);
753 } 713 }
754 cursor = cursor._nextEntry; 714 cursor = cursor._nextEntry;
755 } 715 }
756 } 716 }
757 717
758 /* patch */ V remove(Object key) { 718 void clear() {
759 int hashCode = key.hashCode; 719 _nextEntry = _previousEntry = this;
760 List buckets = _buckets;
761 int index = hashCode & (buckets.length - 1);
762 _LinkedHashMapEntry entry = buckets[index];
763 _HashMapEntry previous = null;
764 while (entry != null) {
765 _HashMapEntry next = entry.next;
766 if (hashCode == entry.hashCode && entry.key == key) {
767 if (previous == null) {
768 buckets[index] = next;
769 } else {
770 previous.next = next;
771 }
772 entry._previousEntry._nextEntry = entry._nextEntry;
773 entry._nextEntry._previousEntry = entry._previousEntry;
774 entry._nextEntry = entry._previousEntry = null;
775 _elementCount--;
776 _modificationCount =
777 (_modificationCount + 1) & _MODIFICATION_COUNT_MASK;
778 return entry.value;
779 }
780 previous = entry;
781 entry = next;
782 }
783 return null;
784 }
785
786 /* patch */ void clear() {
787 _elementCount = 0; 720 _elementCount = 0;
788 _nextEntry = _previousEntry = this; 721 _buckets = new List(_HashMap._INITIAL_CAPACITY);
789 _buckets = new List(_INITIAL_CAPACITY);
790 _modificationCount = (_modificationCount + 1) & _MODIFICATION_COUNT_MASK; 722 _modificationCount = (_modificationCount + 1) & _MODIFICATION_COUNT_MASK;
791 } 723 }
792 724
793 void _addEntry(List buckets, int index, int length, 725 void _addEntry(List buckets, int index, int length,
794 K key, V value, int hashCode) { 726 K key, V value, int hashCode) {
795 _HashMapEntry entry = 727 _HashMapEntry entry =
796 new _LinkedHashMapEntry(key, value, hashCode, buckets[index], 728 new _LinkedHashMapEntry(key, value, hashCode, buckets[index],
797 _previousEntry, this); 729 _previousEntry, this);
798 buckets[index] = entry; 730 buckets[index] = entry;
799 int newElements = _elementCount + 1; 731 int newElements = _elementCount + 1;
800 _elementCount = newElements; 732 _elementCount = newElements;
801 // If we end up with more than 75% non-empty entries, we 733 // If we end up with more than 75% non-empty entries, we
802 // resize the backing store. 734 // resize the backing store.
803 if ((newElements << 2) > ((length << 1) + length)) _resize(); 735 if ((newElements << 2) > ((length << 1) + length)) _resize();
804 _modificationCount = (_modificationCount + 1) & _MODIFICATION_COUNT_MASK; 736 _modificationCount = (_modificationCount + 1) & _MODIFICATION_COUNT_MASK;
805 } 737 }
806 738
807 void _resize() { 739 void _removeEntry(_LinkedHashMapEntry entry,
808 List oldBuckets = _buckets; 740 _HashMapEntry previousInBucket,
809 int oldLength = oldBuckets.length; 741 int bucketIndex) {
810 int newLength = oldLength << 1; 742 var previousInChain = entry._previousEntry;
811 List newBuckets = new List(newLength); 743 var nextInChain = entry._nextEntry;
812 for (int i = 0; i < oldLength; i++) { 744 previousInChain._nextEntry = nextInChain;
813 _HashMapEntry entry = oldBuckets[i]; 745 nextInChain._previousEntry = previousInChain;
814 while (entry != null) { 746 if (previousInBucket == null) {
815 _HashMapEntry next = entry.next; 747 _buckets[bucketIndex] = entry.next;
816 int hashCode = entry.hashCode; 748 } else {
817 int index = hashCode & (newLength - 1); 749 previousInBucket.next = entry.next;
818 entry.next = newBuckets[index];
819 newBuckets[index] = entry;
820 entry = next;
821 }
822 } 750 }
823 _buckets = newBuckets; 751 }
752
753
754 Iterable<K> get keys => new _LinkedHashMapKeyIterable<K>(this);
755 Iterable<V> get values => new _LinkedHashMapValueIterable<V>(this);
756 }
757
758 class _LinkedHashMap<K, V> extends _HashMap<K, V>
759 with _LinkedHashMapMixin<K, V> {
760 _LinkedHashMap() {
761 _nextEntry = _previousEntry = this;
824 } 762 }
825 } 763 }
826 764
765 class _LinkedIdentityHashMap<K, V> extends _IdentityHashMap<K, V>
766 with _LinkedHashMapMixin<K, V> {
767 _LinkedIdentityHashMap() {
768 _nextEntry = _previousEntry = this;
769 }
770 }
771
772 class _LinkedCustomHashMap<K, V> extends _CustomHashMap<K, V>
773 with _LinkedHashMapMixin<K, V> {
774 _LinkedCustomHashMap(bool equals(K key1, K key2),
775 int hashCode(K key),
776 bool isValidKey(potentialKey))
777 : super(equals, hashCode, isValidKey) {
778 _nextEntry = _previousEntry = this;
779 }
780 }
781
782
827 patch class LinkedHashSet<E> extends _HashSetBase<E> { 783 patch class LinkedHashSet<E> extends _HashSetBase<E> {
828 static const int _INITIAL_CAPACITY = 8; 784 static const int _INITIAL_CAPACITY = 8;
829 _LinkedHashTable<E> _table; 785 _LinkedHashTable<E> _table;
830 786
831 /* patch */ LinkedHashSet() { 787 /* patch */ LinkedHashSet() {
832 _table = new _LinkedHashTable(_INITIAL_CAPACITY); 788 _table = new _LinkedHashTable(_INITIAL_CAPACITY);
833 _table._container = this; 789 _table._container = this;
834 } 790 }
835 791
836 // Iterable. 792 // Iterable.
(...skipping 680 matching lines...) Expand 10 before | Expand all | Expand 10 after
1517 1473
1518 _LinkedHashMapTable() : super(_INITIAL_CAPACITY); 1474 _LinkedHashMapTable() : super(_INITIAL_CAPACITY);
1519 1475
1520 V _value(int offset) => _table[offset + _VALUE_INDEX]; 1476 V _value(int offset) => _table[offset + _VALUE_INDEX];
1521 void _setValue(int offset, V value) { _table[offset + _VALUE_INDEX] = value; } 1477 void _setValue(int offset, V value) { _table[offset + _VALUE_INDEX] = value; }
1522 1478
1523 _copyEntry(List oldTable, int fromOffset, int toOffset) { 1479 _copyEntry(List oldTable, int fromOffset, int toOffset) {
1524 _table[toOffset + _VALUE_INDEX] = oldTable[fromOffset + _VALUE_INDEX]; 1480 _table[toOffset + _VALUE_INDEX] = oldTable[fromOffset + _VALUE_INDEX];
1525 } 1481 }
1526 } 1482 }
OLDNEW
« no previous file with comments | « pkg/serialization/test/polyfill_identity_map_test.dart ('k') | sdk/lib/_internal/lib/collection_patch.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698