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

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

Powered by Google App Engine
This is Rietveld 408576698