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

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

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