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 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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 } |
OLD | NEW |