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

Side by Side Diff: lib/coreimpl/hash_map_set.dart

Issue 11227027: Revert 13878 (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 1 month 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
« no previous file with comments | « lib/coreimpl/future_implementation.dart ('k') | lib/coreimpl/linked_hash_map.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 // Hash map implementation with open addressing and quadratic probing. 5 // Hash map implementation with open addressing and quadratic probing.
6 class HashMapImplementation<K, V> implements HashMap<K, V> { 6 class HashMapImplementation<K, V> implements HashMap<K, V> {
7 7
8 // The [_keys] list contains the keys inserted in the map. 8 // The [_keys] list contains the keys inserted in the map.
9 // The [_keys] list must be a raw list because it 9 // The [_keys] list must be a raw list because it
10 // will contain both elements of type K, and the [_DELETED_KEY] of type 10 // will contain both elements of type K, and the [_DELETED_KEY] of type
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
71 int _probeForAdding(K key) { 71 int _probeForAdding(K key) {
72 if (key == null) throw const NullPointerException(); 72 if (key == null) throw const NullPointerException();
73 int hash = _firstProbe(key.hashCode, _keys.length); 73 int hash = _firstProbe(key.hashCode, _keys.length);
74 int numberOfProbes = 1; 74 int numberOfProbes = 1;
75 int initialHash = hash; 75 int initialHash = hash;
76 // insertionIndex points to a slot where a key was deleted. 76 // insertionIndex points to a slot where a key was deleted.
77 int insertionIndex = -1; 77 int insertionIndex = -1;
78 while (true) { 78 while (true) {
79 // [existingKey] can be either of type [K] or [_DeletedKeySentinel]. 79 // [existingKey] can be either of type [K] or [_DeletedKeySentinel].
80 Object existingKey = _keys[hash]; 80 Object existingKey = _keys[hash];
81 if (existingKey == null) { 81 if (existingKey === null) {
82 // We are sure the key is not already in the set. 82 // We are sure the key is not already in the set.
83 // If the current slot is empty and we didn't find any 83 // If the current slot is empty and we didn't find any
84 // insertion slot before, return this slot. 84 // insertion slot before, return this slot.
85 if (insertionIndex < 0) return hash; 85 if (insertionIndex < 0) return hash;
86 // If we did find an insertion slot before, return it. 86 // If we did find an insertion slot before, return it.
87 return insertionIndex; 87 return insertionIndex;
88 } else if (existingKey == key) { 88 } else if (existingKey == key) {
89 // The key is already in the map. Return its slot. 89 // The key is already in the map. Return its slot.
90 return hash; 90 return hash;
91 } else if ((insertionIndex < 0) 91 } else if ((insertionIndex < 0) && (_DELETED_KEY === existingKey)) {
92 && (identical(_DELETED_KEY, existingKey))) {
93 // The slot contains a deleted element. Because previous calls to this 92 // The slot contains a deleted element. Because previous calls to this
94 // method may not have had this slot deleted, we must continue iterate 93 // method may not have had this slot deleted, we must continue iterate
95 // to find if there is a slot with the given key. 94 // to find if there is a slot with the given key.
96 insertionIndex = hash; 95 insertionIndex = hash;
97 } 96 }
98 97
99 // We did not find an insertion slot. Look at the next one. 98 // We did not find an insertion slot. Look at the next one.
100 hash = _nextProbe(hash, numberOfProbes++, _keys.length); 99 hash = _nextProbe(hash, numberOfProbes++, _keys.length);
101 // _ensureCapacity has guaranteed the following cannot happen. 100 // _ensureCapacity has guaranteed the following cannot happen.
102 // assert(hash != initialHash); 101 // assert(hash != initialHash);
103 } 102 }
104 } 103 }
105 104
106 int _probeForLookup(K key) { 105 int _probeForLookup(K key) {
107 if (key == null) throw const NullPointerException(); 106 if (key == null) throw const NullPointerException();
108 int hash = _firstProbe(key.hashCode, _keys.length); 107 int hash = _firstProbe(key.hashCode, _keys.length);
109 int numberOfProbes = 1; 108 int numberOfProbes = 1;
110 int initialHash = hash; 109 int initialHash = hash;
111 while (true) { 110 while (true) {
112 // [existingKey] can be either of type [K] or [_DeletedKeySentinel]. 111 // [existingKey] can be either of type [K] or [_DeletedKeySentinel].
113 Object existingKey = _keys[hash]; 112 Object existingKey = _keys[hash];
114 // If the slot does not contain anything (in particular, it does not 113 // If the slot does not contain anything (in particular, it does not
115 // contain a deleted key), we know the key is not in the map. 114 // contain a deleted key), we know the key is not in the map.
116 if (existingKey == null) return -1; 115 if (existingKey === null) return -1;
117 // The key is in the map, return its index. 116 // The key is in the map, return its index.
118 if (existingKey == key) return hash; 117 if (existingKey == key) return hash;
119 // Go to the next probe. 118 // Go to the next probe.
120 hash = _nextProbe(hash, numberOfProbes++, _keys.length); 119 hash = _nextProbe(hash, numberOfProbes++, _keys.length);
121 // _ensureCapacity has guaranteed the following cannot happen. 120 // _ensureCapacity has guaranteed the following cannot happen.
122 // assert(hash != initialHash); 121 // assert(hash != initialHash);
123 } 122 }
124 } 123 }
125 124
126 void _ensureCapacity() { 125 void _ensureCapacity() {
(...skipping 25 matching lines...) Expand all
152 int capacity = _keys.length; 151 int capacity = _keys.length;
153 _loadLimit = _computeLoadLimit(newCapacity); 152 _loadLimit = _computeLoadLimit(newCapacity);
154 List oldKeys = _keys; 153 List oldKeys = _keys;
155 List<V> oldValues = _values; 154 List<V> oldValues = _values;
156 _keys = new List(newCapacity); 155 _keys = new List(newCapacity);
157 _values = new List<V>(newCapacity); 156 _values = new List<V>(newCapacity);
158 for (int i = 0; i < capacity; i++) { 157 for (int i = 0; i < capacity; i++) {
159 // [key] can be either of type [K] or [_DeletedKeySentinel]. 158 // [key] can be either of type [K] or [_DeletedKeySentinel].
160 Object key = oldKeys[i]; 159 Object key = oldKeys[i];
161 // If there is no key, we don't need to deal with the current slot. 160 // If there is no key, we don't need to deal with the current slot.
162 if (key == null || identical(key, _DELETED_KEY)) { 161 if (key === null || key === _DELETED_KEY) {
163 continue; 162 continue;
164 } 163 }
165 V value = oldValues[i]; 164 V value = oldValues[i];
166 // Insert the {key, value} pair in their new slot. 165 // Insert the {key, value} pair in their new slot.
167 int newIndex = _probeForAdding(key); 166 int newIndex = _probeForAdding(key);
168 _keys[newIndex] = key; 167 _keys[newIndex] = key;
169 _values[newIndex] = value; 168 _values[newIndex] = value;
170 } 169 }
171 _numberOfDeleted = 0; 170 _numberOfDeleted = 0;
172 } 171 }
173 172
174 void clear() { 173 void clear() {
175 _numberOfEntries = 0; 174 _numberOfEntries = 0;
176 _numberOfDeleted = 0; 175 _numberOfDeleted = 0;
177 int length = _keys.length; 176 int length = _keys.length;
178 for (int i = 0; i < length; i++) { 177 for (int i = 0; i < length; i++) {
179 _keys[i] = null; 178 _keys[i] = null;
180 _values[i] = null; 179 _values[i] = null;
181 } 180 }
182 } 181 }
183 182
184 void operator []=(K key, V value) { 183 void operator []=(K key, V value) {
185 _ensureCapacity(); 184 _ensureCapacity();
186 int index = _probeForAdding(key); 185 int index = _probeForAdding(key);
187 if ((_keys[index] == null) || (identical(_keys[index], _DELETED_KEY))) { 186 if ((_keys[index] === null) || (_keys[index] === _DELETED_KEY)) {
188 _numberOfEntries++; 187 _numberOfEntries++;
189 } 188 }
190 _keys[index] = key; 189 _keys[index] = key;
191 _values[index] = value; 190 _values[index] = value;
192 } 191 }
193 192
194 V operator [](K key) { 193 V operator [](K key) {
195 int index = _probeForLookup(key); 194 int index = _probeForLookup(key);
196 if (index < 0) return null; 195 if (index < 0) return null;
197 return _values[index]; 196 return _values[index];
(...skipping 27 matching lines...) Expand all
225 } 224 }
226 225
227 int get length { 226 int get length {
228 return _numberOfEntries; 227 return _numberOfEntries;
229 } 228 }
230 229
231 void forEach(void f(K key, V value)) { 230 void forEach(void f(K key, V value)) {
232 int length = _keys.length; 231 int length = _keys.length;
233 for (int i = 0; i < length; i++) { 232 for (int i = 0; i < length; i++) {
234 var key = _keys[i]; 233 var key = _keys[i];
235 if ((key != null) && (!identical(key, _DELETED_KEY))) { 234 if ((key !== null) && (key !== _DELETED_KEY)) {
236 f(key, _values[i]); 235 f(key, _values[i]);
237 } 236 }
238 } 237 }
239 } 238 }
240 239
241 240
242 Collection<K> getKeys() { 241 Collection<K> getKeys() {
243 List<K> list = new List<K>(length); 242 List<K> list = new List<K>(length);
244 int i = 0; 243 int i = 0;
245 forEach(void _(K key, V value) { 244 forEach(void _(K key, V value) {
(...skipping 12 matching lines...) Expand all
258 } 257 }
259 258
260 bool containsKey(K key) { 259 bool containsKey(K key) {
261 return (_probeForLookup(key) != -1); 260 return (_probeForLookup(key) != -1);
262 } 261 }
263 262
264 bool containsValue(V value) { 263 bool containsValue(V value) {
265 int length = _values.length; 264 int length = _values.length;
266 for (int i = 0; i < length; i++) { 265 for (int i = 0; i < length; i++) {
267 var key = _keys[i]; 266 var key = _keys[i];
268 if ((key != null) && (!identical(key, _DELETED_KEY))) { 267 if ((key !== null) && (key !== _DELETED_KEY)) {
269 if (_values[i] == value) return true; 268 if (_values[i] == value) return true;
270 } 269 }
271 } 270 }
272 return false; 271 return false;
273 } 272 }
274 273
275 String toString() { 274 String toString() {
276 return Maps.mapToString(this); 275 return Maps.mapToString(this);
277 } 276 }
278 } 277 }
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
402 401
403 // TODO(4504458): Replace set_ with set. 402 // TODO(4504458): Replace set_ with set.
404 HashSetIterator(HashSetImplementation<E> set_) 403 HashSetIterator(HashSetImplementation<E> set_)
405 : _nextValidIndex = -1, 404 : _nextValidIndex = -1,
406 _entries = set_._backingMap._keys { 405 _entries = set_._backingMap._keys {
407 _advance(); 406 _advance();
408 } 407 }
409 408
410 bool hasNext() { 409 bool hasNext() {
411 if (_nextValidIndex >= _entries.length) return false; 410 if (_nextValidIndex >= _entries.length) return false;
412 final deletedKey = HashMapImplementation._DELETED_KEY; 411 if (_entries[_nextValidIndex] === HashMapImplementation._DELETED_KEY) {
413 if (identical(_entries[_nextValidIndex], deletedKey)) {
414 // This happens in case the set was modified in the meantime. 412 // This happens in case the set was modified in the meantime.
415 // A modification on the set may make this iterator misbehave, 413 // A modification on the set may make this iterator misbehave,
416 // but we should never return the sentinel. 414 // but we should never return the sentinel.
417 _advance(); 415 _advance();
418 } 416 }
419 return _nextValidIndex < _entries.length; 417 return _nextValidIndex < _entries.length;
420 } 418 }
421 419
422 E next() { 420 E next() {
423 if (!hasNext()) { 421 if (!hasNext()) {
424 throw const NoMoreElementsException(); 422 throw const NoMoreElementsException();
425 } 423 }
426 E res = _entries[_nextValidIndex]; 424 E res = _entries[_nextValidIndex];
427 _advance(); 425 _advance();
428 return res; 426 return res;
429 } 427 }
430 428
431 void _advance() { 429 void _advance() {
432 int length = _entries.length; 430 int length = _entries.length;
433 var entry; 431 var entry;
434 final deletedKey = HashMapImplementation._DELETED_KEY; 432 final deletedKey = HashMapImplementation._DELETED_KEY;
435 do { 433 do {
436 if (++_nextValidIndex >= length) break; 434 if (++_nextValidIndex >= length) break;
437 entry = _entries[_nextValidIndex]; 435 entry = _entries[_nextValidIndex];
438 } while ((entry == null) || (identical(entry, deletedKey))); 436 } while ((entry === null) || (entry === deletedKey));
439 } 437 }
440 438
441 // The entries in the set. May contain null or the sentinel value. 439 // The entries in the set. May contain null or the sentinel value.
442 List<E> _entries; 440 List<E> _entries;
443 441
444 // The next valid index in [_entries] or the length of [entries_]. 442 // The next valid index in [_entries] or the length of [entries_].
445 // If it is the length of [_entries], calling [hasNext] on the 443 // If it is the length of [_entries], calling [hasNext] on the
446 // iterator will return false. 444 // iterator will return false.
447 int _nextValidIndex; 445 int _nextValidIndex;
448 } 446 }
449 447
450 /** 448 /**
451 * A singleton sentinel used to represent when a key is deleted from the map. 449 * A singleton sentinel used to represent when a key is deleted from the map.
452 * We can't use [: const Object() :] as a sentinel because it would end up 450 * We can't use [: const Object() :] as a sentinel because it would end up
453 * canonicalized and then we cannot distinguish the deleted key from the 451 * canonicalized and then we cannot distinguish the deleted key from the
454 * canonicalized [: Object() :]. 452 * canonicalized [: Object() :].
455 */ 453 */
456 class _DeletedKeySentinel { 454 class _DeletedKeySentinel {
457 const _DeletedKeySentinel(); 455 const _DeletedKeySentinel();
458 } 456 }
OLDNEW
« no previous file with comments | « lib/coreimpl/future_implementation.dart ('k') | lib/coreimpl/linked_hash_map.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698