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

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: 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 if (hashCode == null) {
9 if (equals == null) { 9 if (equals == null) {
10 return new _HashMapImpl<K, V>(); 10 return new _HashMap<K, V>();
11 } 11 }
12 if (identical(identical, equals)) { 12 if (identical(identical, equals)) {
13 return new _IdentityHashMap<K, V>(); 13 return new _IdentityHashMap<K, V>();
14 } 14 }
15 hashCode = _defaultHashCode; 15 hashCode = _defaultHashCode;
16 } else if (equals == null) { 16 } else if (equals == null) {
17 equals = _defaultEquals; 17 equals = _defaultEquals;
18 } 18 }
19 return new _CustomHashMap<K, V>(equals, hashCode); 19 return new _CustomHashMap<K, V>(equals, hashCode);
20 } 20 }
21 } 21 }
22 22
23 const int _MODIFICATION_COUNT_MASK = 0x3fffffff; 23 const int _MODIFICATION_COUNT_MASK = 0x3fffffff;
24 24
25 class _HashMapImpl<K, V> implements HashMap<K, V> { 25 class _HashMap<K, V> implements HashMap<K, V> {
26 static const int _INITIAL_CAPACITY = 8; 26 static const int _INITIAL_CAPACITY = 8;
27 27
28 int _elementCount = 0; 28 int _elementCount = 0;
29 List<_HashMapEntry> _buckets = new List(_INITIAL_CAPACITY); 29 List<_HashMapEntry> _buckets = new List(_INITIAL_CAPACITY);
30 int _modificationCount = 0; 30 int _modificationCount = 0;
31 31
32 int get length => _elementCount; 32 int get length => _elementCount;
33 bool get isEmpty => _elementCount == 0; 33 bool get isEmpty => _elementCount == 0;
34 bool get isNotEmpty => _elementCount != 0; 34 bool get isNotEmpty => _elementCount != 0;
35 35
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
194 newBuckets[index] = entry; 194 newBuckets[index] = entry;
195 entry = next; 195 entry = next;
196 } 196 }
197 } 197 }
198 _buckets = newBuckets; 198 _buckets = newBuckets;
199 } 199 }
200 200
201 String toString() => Maps.mapToString(this); 201 String toString() => Maps.mapToString(this);
202 } 202 }
203 203
204 class _CustomHashMap<K, V> extends _HashMapImpl<K, V> { 204 class _CustomHashMap<K, V> extends _HashMap<K, V> {
205 final _Equality<K> _equals; 205 final _Equality<K> _equals;
206 final _Hasher<K> _hashCode; 206 final _Hasher<K> _hashCode;
207 _CustomHashMap(this._equals, this._hashCode); 207 _CustomHashMap(this._equals, this._hashCode);
208 208
209 bool containsKey(Object key) { 209 bool containsKey(Object key) {
210 int hashCode = _hashCode(key); 210 int hashCode = _hashCode(key);
211 List buckets = _buckets; 211 List buckets = _buckets;
212 int index = hashCode & (buckets.length - 1); 212 int index = hashCode & (buckets.length - 1);
213 _HashMapEntry entry = buckets[index]; 213 _HashMapEntry entry = buckets[index];
214 while (entry != null) { 214 while (entry != null) {
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
291 } 291 }
292 previous = entry; 292 previous = entry;
293 entry = next; 293 entry = next;
294 } 294 }
295 return null; 295 return null;
296 } 296 }
297 297
298 String toString() => Maps.mapToString(this); 298 String toString() => Maps.mapToString(this);
299 } 299 }
300 300
301 class _IdentityHashMap<K, V> extends _HashMapImpl<K, V> { 301 class _IdentityHashMap<K, V> extends _HashMap<K, V> {
302 bool containsKey(Object key) { 302 bool containsKey(Object key) {
303 int hashCode = key.hashCode; 303 int hashCode = key.hashCode;
304 List buckets = _buckets; 304 List buckets = _buckets;
305 int index = hashCode & (buckets.length - 1); 305 int index = hashCode & (buckets.length - 1);
306 _HashMapEntry entry = buckets[index]; 306 _HashMapEntry entry = buckets[index];
307 while (entry != null) { 307 while (entry != null) {
308 if (hashCode == entry.hashCode && identical(entry.key, key)) return true; 308 if (hashCode == entry.hashCode && identical(entry.key, key)) return true;
309 entry = entry.next; 309 entry = entry.next;
310 } 310 }
311 return false; 311 return false;
(...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after
589 LinkedHashMap<dynamic, V> _map; 589 LinkedHashMap<dynamic, V> _map;
590 _LinkedHashMapValueIterable(this._map); 590 _LinkedHashMapValueIterable(this._map);
591 Iterator<K> get iterator => new _LinkedHashMapValueIterator<V>(_map); 591 Iterator<K> get iterator => new _LinkedHashMapValueIterator<V>(_map);
592 bool contains(V value) => _map.containsValue(value); 592 bool contains(V value) => _map.containsValue(value);
593 bool get isEmpty => _map.isEmpty; 593 bool get isEmpty => _map.isEmpty;
594 bool get isNotEmpty => _map.isNotEmpty; 594 bool get isNotEmpty => _map.isNotEmpty;
595 int get length => _map.length; 595 int get length => _map.length;
596 } 596 }
597 597
598 abstract class _LinkedHashMapIterator<T> implements Iterator<T> { 598 abstract class _LinkedHashMapIterator<T> implements Iterator<T> {
599 final _LinkedHashMap _map; 599 final LinkedHashMap _map;
600 var _next; 600 var _next;
601 T _current; 601 T _current;
602 int _modificationCount; 602 int _modificationCount;
603 _LinkedHashMapIterator(_LinkedHashMap map) 603 _LinkedHashMapIterator(LinkedHashMap map)
604 : _map = map, 604 : _map = map,
605 _current = null, 605 _current = null,
606 _next = map._nextEntry, 606 _next = map._nextEntry,
607 _modificationCount = map._modificationCount; 607 _modificationCount = map._modificationCount;
608 608
609 bool moveNext() { 609 bool moveNext() {
610 if (_modificationCount != _map._modificationCount) { 610 if (_modificationCount != _map._modificationCount) {
611 throw new ConcurrentModificationError(_map); 611 throw new ConcurrentModificationError(_map);
612 } 612 }
613 if (identical(_map, _next)) { 613 if (identical(_map, _next)) {
614 _current = null; 614 _current = null;
615 return false; 615 return false;
616 } 616 }
617 _LinkedHashMapEntry entry = _next; 617 _LinkedHashMapEntry entry = _next;
618 _next = entry._nextEntry; 618 _next = entry._nextEntry;
619 _current = _getValue(entry); 619 _current = _getValue(entry);
620 return true; 620 return true;
621 } 621 }
622 622
623 T _getValue(_LinkedHashMapEntry entry); 623 T _getValue(_LinkedHashMapEntry entry);
624 624
625 T get current => _current; 625 T get current => _current;
626 } 626 }
627 627
628 class _LinkedHashMapKeyIterator<K> extends _LinkedHashMapIterator<K> { 628 class _LinkedHashMapKeyIterator<K> extends _LinkedHashMapIterator<K> {
629 _LinkedHashMapKeyIterator(_LinkedHashMap map) : super(map); 629 _LinkedHashMapKeyIterator(LinkedHashMap map) : super(map);
630 K _getValue(_LinkedHashMapEntry entry) => entry.key; 630 K _getValue(_LinkedHashMapEntry entry) => entry.key;
631 } 631 }
632 632
633 class _LinkedHashMapValueIterator<V> extends _LinkedHashMapIterator<V> { 633 class _LinkedHashMapValueIterator<V> extends _LinkedHashMapIterator<V> {
634 _LinkedHashMapValueIterator(_LinkedHashMap map) : super(map); 634 _LinkedHashMapValueIterator(LinkedHashMap map) : super(map);
635 V _getValue(_LinkedHashMapEntry entry) => entry.value; 635 V _getValue(_LinkedHashMapEntry entry) => entry.value;
636 } 636 }
637 637
638 638
639 /** 639 /**
640 * A hash-based map that iterates keys and values in key insertion order. 640 * A hash-based map that iterates keys and values in key insertion order.
641 */ 641 */
642 patch class LinkedHashMap<K, V> { 642 patch class LinkedHashMap<K, V> {
643 static const int _INITIAL_CAPACITY = 8; 643 var _nextEntry;
644 static const int _MODIFICATION_COUNT_MASK = 0x3fffffff; 644 var _previousEntry;
645 645
646 int _elementCount = 0; 646 /* patch */ factory LinkedHashMap({ bool equals(K key1, K key2),
647 List<_HashMapEntry> _buckets = new List(_INITIAL_CAPACITY); 647 int hashCode(K key) }) {
648 int _modificationCount = 0; 648 if (hashCode == null) {
649 649 if (equals == null) {
650 var _nextEntry; 650 return new _LinkedHashMap<K, V>();
651 var _previousEntry; 651 }
652 652 if (identical(identical, equals)) {
653 /* patch */ LinkedHashMap() { 653 return new _LinkedIdentityHashMap<K, V>();
654 _nextEntry = _previousEntry = this; 654 }
655 } 655 hashCode = _defaultHashCode;
656 656 } else if (equals == null) {
657 /* patch */ int get length => _elementCount; 657 equals = _defaultEquals;
658 /* patch */ bool get isEmpty => _elementCount == 0; 658 }
659 /* patch */ bool get isNotEmpty => _elementCount != 0; 659 return new _LinkedCustomHashMap<K, V>(equals, hashCode);
660 660 }
661 /* patch */ Iterable<K> get keys => new _LinkedHashMapKeyIterable<K>(this); 661 }
662 /* patch */ Iterable<V> get values => new _LinkedHashMapValueIterable<V>(this) ; 662
663 663 class _LinkedHashMap<K, V> extends _HashMap<K, V>
664 /* patch */ bool containsKey(Object key) { 664 implements LinkedHashMap<K, V> {
floitsch 2013/09/05 13:44:28 nit: indentation.
Lasse Reichstein Nielsen 2013/09/06 08:49:24 Done.
665 int hashCode = key.hashCode; 665 var _nextEntry;
666 List buckets = _buckets; 666 var _previousEntry;
667 int index = hashCode & (buckets.length - 1); 667
668 _HashMapEntry entry = buckets[index]; 668 _LinkedHashMap() {
669 while (entry != null) { 669 _nextEntry = _previousEntry = this;
670 if (hashCode == entry.hashCode && entry.key == key) return true; 670 }
671 entry = entry.next; 671
672 bool containsValue(Object value) {
673 int modificationCount = _modificationCount;
674 var cursor = _nextEntry;
675 while (!identical(cursor, this)) {
676 _HashMapEntry entry = cursor;
677 if (entry.value == value) return true;
678 if (modificationCount != _modificationCount) {
679 throw new ConcurrentModificationError(this);
680 }
681 cursor = cursor._nextEntry;
672 } 682 }
673 return false; 683 return false;
674 } 684 }
675 685
676 /* patch */ bool containsValue(Object value) { 686 void forEach(void action(K key, V value)) {
677 var cursor = _nextEntry; 687 int modificationCount = _modificationCount;
678 int modificationCount = _modificationCount;
679 while (!identical(cursor, this)) {
680 _HashMapEntry entry = cursor;
681 if (entry.value == value) return true;
682 cursor = cursor._nextEntry;
683 }
684 return false;
685 }
686
687 /* patch */ V operator[](Object key) {
688 int hashCode = key.hashCode;
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; 688 var cursor = _nextEntry;
748 while (!identical(cursor, this)) { 689 while (!identical(cursor, this)) {
749 _HashMapEntry entry = cursor; 690 _HashMapEntry entry = cursor;
750 action(entry.key, entry.value); 691 action(entry.key, entry.value);
751 if (stamp != _modificationCount) { 692 if (modificationCount != _modificationCount) {
752 throw new ConcurrentModificationError(this); 693 throw new ConcurrentModificationError(this);
753 } 694 }
754 cursor = cursor._nextEntry; 695 cursor = cursor._nextEntry;
755 } 696 }
756 } 697 }
757 698
758 /* patch */ V remove(Object key) { 699 /* patch */ V remove(Object key) {
759 int hashCode = key.hashCode; 700 int hashCode = key.hashCode;
760 List buckets = _buckets; 701 List buckets = _buckets;
761 int index = hashCode & (buckets.length - 1); 702 int index = hashCode & (buckets.length - 1);
762 _LinkedHashMapEntry entry = buckets[index]; 703 _LinkedHashMapEntry entry = buckets[index];
763 _HashMapEntry previous = null; 704 _HashMapEntry previous = null;
764 while (entry != null) { 705 while (entry != null) {
765 _HashMapEntry next = entry.next; 706 _HashMapEntry next = entry.next;
766 if (hashCode == entry.hashCode && entry.key == key) { 707 if (hashCode == entry.hashCode && entry.key == key) {
767 if (previous == null) { 708 if (previous == null) {
768 buckets[index] = next; 709 buckets[index] = next;
769 } else { 710 } else {
711 previous.next = next;
712 }
713 entry._previousEntry._nextEntry = entry._nextEntry;
floitsch 2013/09/05 13:44:28 As usual: I prefer temporary variables: previous =
floitsch 2013/09/05 13:44:28 Starting at this line this code is the same for al
Lasse Reichstein Nielsen 2013/09/06 08:49:24 Similar code. It may differ on equality and hashco
714 entry._nextEntry._previousEntry = entry._previousEntry;
715 entry._nextEntry = entry._previousEntry = null;
716 _elementCount--;
717 _modificationCount =
718 (_modificationCount + 1) & _MODIFICATION_COUNT_MASK;
719 return entry.value;
720 }
721 previous = entry;
722 entry = next;
723 }
724 return null;
725 }
726
727 void clear() {
728 _nextEntry = _previousEntry = this;
729 super.clear();
730 }
731
732 void _addEntry(List buckets, int index, int length,
floitsch 2013/09/05 13:44:28 same code too. right?
Lasse Reichstein Nielsen 2013/09/06 08:49:24 Exactly same code in all three sub-classes, yes.
733 K key, V value, int hashCode) {
734 _HashMapEntry entry =
735 new _LinkedHashMapEntry(key, value, hashCode, buckets[index],
736 _previousEntry, this);
737 buckets[index] = entry;
738 int newElements = _elementCount + 1;
739 _elementCount = newElements;
740 // If we end up with more than 75% non-empty entries, we
741 // resize the backing store.
742 if ((newElements << 2) > ((length << 1) + length)) _resize();
743 _modificationCount = (_modificationCount + 1) & _MODIFICATION_COUNT_MASK;
744 }
745
746 Iterable<K> get keys => new _LinkedHashMapKeyIterable<K>(this);
747 Iterable<V> get values => new _LinkedHashMapValueIterable<V>(this);
748 }
749
750 class _LinkedIdentityHashMap<K, V> extends _IdentityHashMap<K, V>
751 implements LinkedHashMap<K, V> {
752 var _nextEntry;
753 var _previousEntry;
754
755 _LinkedIdentityHashMap() {
756 _nextEntry = _previousEntry = this;
757 }
758
759 bool containsValue(Object value) {
760 int modificationCount = _modificationCount;
761 var cursor = _nextEntry;
762 while (!identical(cursor, this)) {
763 _HashMapEntry entry = cursor;
764 if (entry.value == value) return true;
765 if (modificationCount != _modificationCount) {
766 throw new ConcurrentModificationError(this);
767 }
768 cursor = cursor._nextEntry;
769 }
770 return false;
771 }
772
773 void forEach(void action(K key, V value)) {
774 int modificationCount = _modificationCount;
775 var cursor = _nextEntry;
776 while (!identical(cursor, this)) {
777 _HashMapEntry entry = cursor;
778 action(entry.key, entry.value);
779 if (modificationCount != _modificationCount) {
780 throw new ConcurrentModificationError(this);
781 }
782 cursor = cursor._nextEntry;
783 }
784 }
785
786 V remove(Object key) {
787 int hashCode = key.hashCode;
788 List buckets = _buckets;
789 int index = hashCode & (buckets.length - 1);
790 _LinkedHashMapEntry entry = buckets[index];
791 _HashMapEntry previous = null;
792 while (entry != null) {
793 _HashMapEntry next = entry.next;
794 if (hashCode == entry.hashCode && identical(entry.key, key)) {
795 if (previous == null) {
796 buckets[index] = next;
797 } else {
798 previous.next = next;
799 }
800 entry._previousEntry._nextEntry = entry._nextEntry;
floitsch 2013/09/05 13:44:28 temporary variables.
Lasse Reichstein Nielsen 2013/09/06 08:49:24 Done.
801 entry._nextEntry._previousEntry = entry._previousEntry;
802 entry._nextEntry = entry._previousEntry = null;
803 _elementCount--;
804 _modificationCount =
805 (_modificationCount + 1) & _MODIFICATION_COUNT_MASK;
806 return entry.value;
807 }
808 previous = entry;
809 entry = next;
810 }
811 return null;
812 }
813
814 void clear() {
815 _nextEntry = _previousEntry = this;
816 super.clear();
817 }
818
819 void _addEntry(List buckets, int index, int length,
820 K key, V value, int hashCode) {
821 buckets[index] =
822 new _LinkedHashMapEntry(key, value, hashCode, buckets[index],
823 _previousEntry, this);
824 int newElements = _elementCount + 1;
825 _elementCount = newElements;
826 // If we end up with more than 75% non-empty entries, we
827 // resize the backing store.
828 if ((newElements << 2) > ((length << 1) + length)) _resize();
829 _modificationCount = (_modificationCount + 1) & _MODIFICATION_COUNT_MASK;
830 }
831
832 Iterable<K> get keys => new _LinkedHashMapKeyIterable<K>(this);
833 Iterable<V> get values => new _LinkedHashMapValueIterable<V>(this);
834 }
835
836 class _LinkedCustomHashMap<K, V> extends _CustomHashMap<K, V>
837 implements LinkedHashMap<K, V> {
838 var _nextEntry;
839 var _previousEntry;
840
841 _LinkedCustomHashMap(bool equals(K key1, K key2),
842 int hashCode(K key))
843 : super(equals, hashCode) {
844 _nextEntry = _previousEntry = this;
845 }
846
847 bool containsValue(Object value) {
848 int modificationCount = _modificationCount;
849 var cursor = _nextEntry;
850 while (!identical(cursor, this)) {
851 _HashMapEntry entry = cursor;
852 if (entry.value == value) return true;
853 if (modificationCount != _modificationCount) {
854 throw new ConcurrentModificationError(this);
855 }
856 cursor = cursor._nextEntry;
857 }
858 return false;
859 }
860
861 void forEach(void action(K key, V value)) {
862 int modificationCount = _modificationCount;
863 var cursor = _nextEntry;
864 while (!identical(cursor, this)) {
865 _HashMapEntry entry = cursor;
866 action(entry.key, entry.value);
867 if (modificationCount != _modificationCount) {
868 throw new ConcurrentModificationError(this);
869 }
870 cursor = cursor._nextEntry;
871 }
872 }
873
874 V remove(Object key) {
875 int hashCode = _hashCode(key);
876 List buckets = _buckets;
877 int index = hashCode & (buckets.length - 1);
878 _LinkedHashMapEntry entry = buckets[index];
879 _HashMapEntry previous = null;
880 while (entry != null) {
881 _HashMapEntry next = entry.next;
882 if (hashCode == entry.hashCode && _equals(entry.key, key)) {
883 if (previous == null) {
884 buckets[index] = next;
885 } else {
770 previous.next = next; 886 previous.next = next;
771 } 887 }
772 entry._previousEntry._nextEntry = entry._nextEntry; 888 entry._previousEntry._nextEntry = entry._nextEntry;
floitsch 2013/09/05 13:44:28 ditto.
Lasse Reichstein Nielsen 2013/09/06 08:49:24 Done.
773 entry._nextEntry._previousEntry = entry._previousEntry; 889 entry._nextEntry._previousEntry = entry._previousEntry;
774 entry._nextEntry = entry._previousEntry = null; 890 entry._nextEntry = entry._previousEntry = null;
775 _elementCount--; 891 _elementCount--;
776 _modificationCount = 892 _modificationCount =
777 (_modificationCount + 1) & _MODIFICATION_COUNT_MASK; 893 (_modificationCount + 1) & _MODIFICATION_COUNT_MASK;
778 return entry.value; 894 return entry.value;
779 } 895 }
780 previous = entry; 896 previous = entry;
781 entry = next; 897 entry = next;
782 } 898 }
783 return null; 899 return null;
784 } 900 }
785 901
786 /* patch */ void clear() { 902 void clear() {
787 _elementCount = 0;
788 _nextEntry = _previousEntry = this; 903 _nextEntry = _previousEntry = this;
789 _buckets = new List(_INITIAL_CAPACITY); 904 super.clear();
790 _modificationCount = (_modificationCount + 1) & _MODIFICATION_COUNT_MASK;
791 } 905 }
792 906
793 void _addEntry(List buckets, int index, int length, 907 void _addEntry(List buckets, int index, int length,
794 K key, V value, int hashCode) { 908 K key, V value, int hashCode) {
795 _HashMapEntry entry = 909 buckets[index] =
796 new _LinkedHashMapEntry(key, value, hashCode, buckets[index], 910 new _LinkedHashMapEntry(key, value, hashCode, buckets[index],
797 _previousEntry, this); 911 _previousEntry, this);
798 buckets[index] = entry;
799 int newElements = _elementCount + 1; 912 int newElements = _elementCount + 1;
800 _elementCount = newElements; 913 _elementCount = newElements;
801 // If we end up with more than 75% non-empty entries, we 914 // If we end up with more than 75% non-empty entries, we
802 // resize the backing store. 915 // resize the backing store.
803 if ((newElements << 2) > ((length << 1) + length)) _resize(); 916 if ((newElements << 2) > ((length << 1) + length)) _resize();
804 _modificationCount = (_modificationCount + 1) & _MODIFICATION_COUNT_MASK; 917 _modificationCount = (_modificationCount + 1) & _MODIFICATION_COUNT_MASK;
805 } 918 }
806 919
807 void _resize() { 920 Iterable<K> get keys => new _LinkedHashMapKeyIterable<K>(this);
808 List oldBuckets = _buckets; 921 Iterable<V> get values => new _LinkedHashMapValueIterable<V>(this);
809 int oldLength = oldBuckets.length;
810 int newLength = oldLength << 1;
811 List newBuckets = new List(newLength);
812 for (int i = 0; i < oldLength; i++) {
813 _HashMapEntry entry = oldBuckets[i];
814 while (entry != null) {
815 _HashMapEntry next = entry.next;
816 int hashCode = entry.hashCode;
817 int index = hashCode & (newLength - 1);
818 entry.next = newBuckets[index];
819 newBuckets[index] = entry;
820 entry = next;
821 }
822 }
823 _buckets = newBuckets;
824 }
825 } 922 }
826 923
924
827 patch class LinkedHashSet<E> extends _HashSetBase<E> { 925 patch class LinkedHashSet<E> extends _HashSetBase<E> {
828 static const int _INITIAL_CAPACITY = 8; 926 static const int _INITIAL_CAPACITY = 8;
829 _LinkedHashTable<E> _table; 927 _LinkedHashTable<E> _table;
830 928
831 /* patch */ LinkedHashSet() { 929 /* patch */ LinkedHashSet() {
832 _table = new _LinkedHashTable(_INITIAL_CAPACITY); 930 _table = new _LinkedHashTable(_INITIAL_CAPACITY);
833 _table._container = this; 931 _table._container = this;
834 } 932 }
835 933
836 // Iterable. 934 // Iterable.
(...skipping 680 matching lines...) Expand 10 before | Expand all | Expand 10 after
1517 1615
1518 _LinkedHashMapTable() : super(_INITIAL_CAPACITY); 1616 _LinkedHashMapTable() : super(_INITIAL_CAPACITY);
1519 1617
1520 V _value(int offset) => _table[offset + _VALUE_INDEX]; 1618 V _value(int offset) => _table[offset + _VALUE_INDEX];
1521 void _setValue(int offset, V value) { _table[offset + _VALUE_INDEX] = value; } 1619 void _setValue(int offset, V value) { _table[offset + _VALUE_INDEX] = value; }
1522 1620
1523 _copyEntry(List oldTable, int fromOffset, int toOffset) { 1621 _copyEntry(List oldTable, int fromOffset, int toOffset) {
1524 _table[toOffset + _VALUE_INDEX] = oldTable[fromOffset + _VALUE_INDEX]; 1622 _table[toOffset + _VALUE_INDEX] = oldTable[fromOffset + _VALUE_INDEX];
1525 } 1623 }
1526 } 1624 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698