OLD | NEW |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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 part of dart.core; | 5 part of dart.core; |
6 | 6 |
7 /** | 7 /** |
8 * A [Map] is an associative container, mapping a key to a value. | 8 * A [Map] is an associative container, mapping a key to a value. |
9 * Null values are supported, but null keys are not. | 9 * Null values are supported, but null keys are not. |
10 */ | 10 */ |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
62 * Removes all pairs from the map. | 62 * Removes all pairs from the map. |
63 */ | 63 */ |
64 void clear(); | 64 void clear(); |
65 | 65 |
66 /** | 66 /** |
67 * Applies [f] to each {key, value} pair of the map. | 67 * Applies [f] to each {key, value} pair of the map. |
68 */ | 68 */ |
69 void forEach(void f(K key, V value)); | 69 void forEach(void f(K key, V value)); |
70 | 70 |
71 /** | 71 /** |
72 * Returns a collection containing all the keys in the map. | 72 * The keys of [this]. |
73 */ | 73 */ |
74 Collection<K> get keys; | 74 // TODO(floitsch): this should return a [Set]. |
| 75 Iterable<K> get keys; |
75 | 76 |
76 /** | 77 /** |
77 * Returns a collection containing all the values in the map. | 78 * The values of [this]. |
78 */ | 79 */ |
79 Collection<V> get values; | 80 Iterable<V> get values; |
80 | 81 |
81 /** | 82 /** |
82 * The number of {key, value} pairs in the map. | 83 * The number of {key, value} pairs in the map. |
83 */ | 84 */ |
84 int get length; | 85 int get length; |
85 | 86 |
86 /** | 87 /** |
87 * Returns true if there is no {key, value} pair in the map. | 88 * Returns true if there is no {key, value} pair in the map. |
88 */ | 89 */ |
89 bool get isEmpty; | 90 bool get isEmpty; |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
161 // The sentinel when a key is deleted from the map. | 162 // The sentinel when a key is deleted from the map. |
162 static const _DeletedKeySentinel _DELETED_KEY = const _DeletedKeySentinel(); | 163 static const _DeletedKeySentinel _DELETED_KEY = const _DeletedKeySentinel(); |
163 | 164 |
164 // The initial capacity of a hash map. | 165 // The initial capacity of a hash map. |
165 static const int _INITIAL_CAPACITY = 8; // must be power of 2 | 166 static const int _INITIAL_CAPACITY = 8; // must be power of 2 |
166 | 167 |
167 _HashMapImpl() { | 168 _HashMapImpl() { |
168 _numberOfEntries = 0; | 169 _numberOfEntries = 0; |
169 _numberOfDeleted = 0; | 170 _numberOfDeleted = 0; |
170 _loadLimit = _computeLoadLimit(_INITIAL_CAPACITY); | 171 _loadLimit = _computeLoadLimit(_INITIAL_CAPACITY); |
171 _keys = new List(_INITIAL_CAPACITY); | 172 _keys = new List.fixedLength(_INITIAL_CAPACITY); |
172 _values = new List<V>(_INITIAL_CAPACITY); | 173 _values = new List<V>.fixedLength(_INITIAL_CAPACITY); |
173 } | 174 } |
174 | 175 |
175 factory _HashMapImpl.from(Map<K, V> other) { | 176 factory _HashMapImpl.from(Map<K, V> other) { |
176 Map<K, V> result = new _HashMapImpl<K, V>(); | 177 Map<K, V> result = new _HashMapImpl<K, V>(); |
177 other.forEach((K key, V value) { result[key] = value; }); | 178 other.forEach((K key, V value) { result[key] = value; }); |
178 return result; | 179 return result; |
179 } | 180 } |
180 | 181 |
181 static int _computeLoadLimit(int capacity) { | 182 static int _computeLoadLimit(int capacity) { |
182 return (capacity * 3) ~/ 4; | 183 return (capacity * 3) ~/ 4; |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
268 static bool _isPowerOfTwo(int x) { | 269 static bool _isPowerOfTwo(int x) { |
269 return ((x & (x - 1)) == 0); | 270 return ((x & (x - 1)) == 0); |
270 } | 271 } |
271 | 272 |
272 void _grow(int newCapacity) { | 273 void _grow(int newCapacity) { |
273 assert(_isPowerOfTwo(newCapacity)); | 274 assert(_isPowerOfTwo(newCapacity)); |
274 int capacity = _keys.length; | 275 int capacity = _keys.length; |
275 _loadLimit = _computeLoadLimit(newCapacity); | 276 _loadLimit = _computeLoadLimit(newCapacity); |
276 List oldKeys = _keys; | 277 List oldKeys = _keys; |
277 List<V> oldValues = _values; | 278 List<V> oldValues = _values; |
278 _keys = new List(newCapacity); | 279 _keys = new List.fixedLength(newCapacity); |
279 _values = new List<V>(newCapacity); | 280 _values = new List<V>.fixedLength(newCapacity); |
280 for (int i = 0; i < capacity; i++) { | 281 for (int i = 0; i < capacity; i++) { |
281 // [key] can be either of type [K] or [_DeletedKeySentinel]. | 282 // [key] can be either of type [K] or [_DeletedKeySentinel]. |
282 Object key = oldKeys[i]; | 283 Object key = oldKeys[i]; |
283 // If there is no key, we don't need to deal with the current slot. | 284 // If there is no key, we don't need to deal with the current slot. |
284 if (key == null || identical(key, _DELETED_KEY)) { | 285 if (key == null || identical(key, _DELETED_KEY)) { |
285 continue; | 286 continue; |
286 } | 287 } |
287 V value = oldValues[i]; | 288 V value = oldValues[i]; |
288 // Insert the {key, value} pair in their new slot. | 289 // Insert the {key, value} pair in their new slot. |
289 int newIndex = _probeForAdding(key); | 290 int newIndex = _probeForAdding(key); |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
344 | 345 |
345 bool get isEmpty { | 346 bool get isEmpty { |
346 return _numberOfEntries == 0; | 347 return _numberOfEntries == 0; |
347 } | 348 } |
348 | 349 |
349 int get length { | 350 int get length { |
350 return _numberOfEntries; | 351 return _numberOfEntries; |
351 } | 352 } |
352 | 353 |
353 void forEach(void f(K key, V value)) { | 354 void forEach(void f(K key, V value)) { |
354 int length = _keys.length; | 355 Iterator<int> it = new _HashMapImplIndexIterator(this); |
355 for (int i = 0; i < length; i++) { | 356 while (it.moveNext()) { |
356 var key = _keys[i]; | 357 f(_keys[it.current], _values[it.current]); |
357 if ((key != null) && (!identical(key, _DELETED_KEY))) { | |
358 f(key, _values[i]); | |
359 } | |
360 } | 358 } |
361 } | 359 } |
362 | 360 |
| 361 Iterable<K> get keys => new _HashMapImplKeyIterable<K>(this); |
363 | 362 |
364 Collection<K> get keys { | 363 Iterable<V> get values => new _HashMapImplValueIterable<V>(this); |
365 List<K> list = new List<K>(length); | |
366 int i = 0; | |
367 forEach((K key, V value) { | |
368 list[i++] = key; | |
369 }); | |
370 return list; | |
371 } | |
372 | |
373 Collection<V> get values { | |
374 List<V> list = new List<V>(length); | |
375 int i = 0; | |
376 forEach((K key, V value) { | |
377 list[i++] = value; | |
378 }); | |
379 return list; | |
380 } | |
381 | 364 |
382 bool containsKey(K key) { | 365 bool containsKey(K key) { |
383 return (_probeForLookup(key) != -1); | 366 return (_probeForLookup(key) != -1); |
384 } | 367 } |
385 | 368 |
386 bool containsValue(V value) { | 369 bool containsValue(V value) => values.contains(value); |
387 int length = _values.length; | |
388 for (int i = 0; i < length; i++) { | |
389 var key = _keys[i]; | |
390 if ((key != null) && (!identical(key, _DELETED_KEY))) { | |
391 if (_values[i] == value) return true; | |
392 } | |
393 } | |
394 return false; | |
395 } | |
396 | 370 |
397 String toString() { | 371 String toString() { |
398 return Maps.mapToString(this); | 372 return Maps.mapToString(this); |
399 } | 373 } |
400 } | 374 } |
401 | 375 |
| 376 class _HashMapImplKeyIterable<E> extends Iterable<E> { |
| 377 final _HashMapImpl _map; |
| 378 _HashMapImplKeyIterable(this._map); |
| 379 |
| 380 Iterator<E> get iterator => new _HashMapImplKeyIterator<E>(_map); |
| 381 } |
| 382 |
| 383 class _HashMapImplValueIterable<E> extends Iterable<E> { |
| 384 final _HashMapImpl _map; |
| 385 _HashMapImplValueIterable(this._map); |
| 386 |
| 387 Iterator<E> get iterator => new _HashMapImplValueIterator<E>(_map); |
| 388 } |
| 389 |
| 390 abstract class _HashMapImplIterator<E> implements Iterator<E> { |
| 391 final _HashMapImpl _map; |
| 392 int _index = -1; |
| 393 E _current; |
| 394 |
| 395 _HashMapImplIterator(this._map); |
| 396 |
| 397 E _computeCurrentFromIndex(int index, List keys, List values); |
| 398 |
| 399 bool moveNext() { |
| 400 int length = _map._keys.length; |
| 401 int newIndex = _index + 1; |
| 402 while (newIndex < length) { |
| 403 var key = _map._keys[newIndex]; |
| 404 if ((key != null) && (!identical(key, _HashMapImpl._DELETED_KEY))) { |
| 405 _current = _computeCurrentFromIndex(newIndex, _map._keys, _map._values); |
| 406 _index = newIndex; |
| 407 return true; |
| 408 } |
| 409 newIndex++; |
| 410 } |
| 411 _index = length; |
| 412 _current = null; |
| 413 return false; |
| 414 } |
| 415 |
| 416 E get current => _current; |
| 417 } |
| 418 |
| 419 class _HashMapImplKeyIterator<E> extends _HashMapImplIterator<E> { |
| 420 _HashMapImplKeyIterator(_HashMapImpl map) : super(map); |
| 421 |
| 422 E _computeCurrentFromIndex(int index, List keys, List values) { |
| 423 return keys[index]; |
| 424 } |
| 425 } |
| 426 |
| 427 class _HashMapImplValueIterator<E> extends _HashMapImplIterator<E> { |
| 428 _HashMapImplValueIterator(_HashMapImpl map) : super(map); |
| 429 |
| 430 E _computeCurrentFromIndex(int index, List keys, List values) { |
| 431 return values[index]; |
| 432 } |
| 433 } |
| 434 |
| 435 class _HashMapImplIndexIterator extends _HashMapImplIterator<int> { |
| 436 _HashMapImplIndexIterator(_HashMapImpl map) : super(map); |
| 437 |
| 438 int _computeCurrentFromIndex(int index, List keys, List values) { |
| 439 return index; |
| 440 } |
| 441 } |
402 | 442 |
403 /** | 443 /** |
404 * A singleton sentinel used to represent when a key is deleted from the map. | 444 * A singleton sentinel used to represent when a key is deleted from the map. |
405 * We can't use [: const Object() :] as a sentinel because it would end up | 445 * We can't use [: const Object() :] as a sentinel because it would end up |
406 * canonicalized and then we cannot distinguish the deleted key from the | 446 * canonicalized and then we cannot distinguish the deleted key from the |
407 * canonicalized [: Object() :]. | 447 * canonicalized [: Object() :]. |
408 */ | 448 */ |
409 class _DeletedKeySentinel { | 449 class _DeletedKeySentinel { |
410 const _DeletedKeySentinel(); | 450 const _DeletedKeySentinel(); |
411 } | 451 } |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
466 | 506 |
467 V putIfAbsent(K key, V ifAbsent()) { | 507 V putIfAbsent(K key, V ifAbsent()) { |
468 V value = this[key]; | 508 V value = this[key]; |
469 if ((this[key] == null) && !(containsKey(key))) { | 509 if ((this[key] == null) && !(containsKey(key))) { |
470 value = ifAbsent(); | 510 value = ifAbsent(); |
471 this[key] = value; | 511 this[key] = value; |
472 } | 512 } |
473 return value; | 513 return value; |
474 } | 514 } |
475 | 515 |
476 Collection<K> get keys { | 516 Iterable<K> get keys { |
477 List<K> list = new List<K>(length); | 517 return new MappedIterable<_KeyValuePair<K, V>, K>( |
478 int index = 0; | 518 _list, (_KeyValuePair<K, V> entry) => entry.key); |
479 _list.forEach((_KeyValuePair<K, V> entry) { | |
480 list[index++] = entry.key; | |
481 }); | |
482 assert(index == length); | |
483 return list; | |
484 } | 519 } |
485 | 520 |
486 | 521 |
487 Collection<V> get values { | 522 Iterable<V> get values { |
488 List<V> list = new List<V>(length); | 523 return new MappedIterable<_KeyValuePair<K, V>, V>( |
489 int index = 0; | 524 _list, (_KeyValuePair<K, V> entry) => entry.value); |
490 _list.forEach((_KeyValuePair<K, V> entry) { | |
491 list[index++] = entry.value; | |
492 }); | |
493 assert(index == length); | |
494 return list; | |
495 } | 525 } |
496 | 526 |
497 void forEach(void f(K key, V value)) { | 527 void forEach(void f(K key, V value)) { |
498 _list.forEach((_KeyValuePair<K, V> entry) { | 528 _list.forEach((_KeyValuePair<K, V> entry) { |
499 f(entry.key, entry.value); | 529 f(entry.key, entry.value); |
500 }); | 530 }); |
501 } | 531 } |
502 | 532 |
503 bool containsKey(K key) { | 533 bool containsKey(K key) { |
504 return _map.containsKey(key); | 534 return _map.containsKey(key); |
505 } | 535 } |
506 | 536 |
507 bool containsValue(V value) { | 537 bool containsValue(V value) { |
508 return _list.some((_KeyValuePair<K, V> entry) { | 538 return _list.any((_KeyValuePair<K, V> entry) { |
509 return (entry.value == value); | 539 return (entry.value == value); |
510 }); | 540 }); |
511 } | 541 } |
512 | 542 |
513 int get length { | 543 int get length { |
514 return _map.length; | 544 return _map.length; |
515 } | 545 } |
516 | 546 |
517 bool get isEmpty { | 547 bool get isEmpty { |
518 return length == 0; | 548 return length == 0; |
519 } | 549 } |
520 | 550 |
521 void clear() { | 551 void clear() { |
522 _map.clear(); | 552 _map.clear(); |
523 _list.clear(); | 553 _list.clear(); |
524 } | 554 } |
525 | 555 |
526 String toString() { | 556 String toString() { |
527 return Maps.mapToString(this); | 557 return Maps.mapToString(this); |
528 } | 558 } |
529 } | 559 } |
| 560 |
OLD | NEW |