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

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

Powered by Google App Engine
This is Rietveld 408576698