Chromium Code Reviews| Index: sdk/lib/collection/maps.dart |
| diff --git a/sdk/lib/collection/maps.dart b/sdk/lib/collection/maps.dart |
| index 2d605e8e13a02b7e45c22188bdad4419796e6a1e..28c2e806fadb5daabeee9c5bbb3b2ba37ea1a0e3 100644 |
| --- a/sdk/lib/collection/maps.dart |
| +++ b/sdk/lib/collection/maps.dart |
| @@ -5,6 +5,192 @@ |
| part of dart.collection; |
| /** |
| + * Base class for implementing a [Map]. |
| + * |
| + * This class has a basic implementation of all but five of the members of |
| + * [Map]. |
| + * A basic `Map` class can be implemented by extending this class and |
| + * implementing `keys`, `operator[]`, `operator[]=`, `remove` and `clear`. |
| + * The remaining operations are implemented in terms of these five. |
| + * |
| + * The `keys` iterable should have efficient [length] and [contains] |
| + * operations, and it should catch concurrent modifications of the keys |
| + * while iterating. |
| + * |
| + * A more efficient implementation is usually possible by also overriding |
|
floitsch
2014/03/25 21:03:18
also ... as well
Remove either "also" or "as well"
Lasse Reichstein Nielsen
2014/03/26 10:25:20
Done.
|
| + * some of the other members as well. |
| + */ |
| +class MapBase<K, V> implements Map<K, V> { |
| + Iterable<K> get keys; |
| + V operator[](Object key); |
| + operator []=(K key, V value); |
| + V remove(Object key); |
| + // The `clear` operation should not be based on `remove`. |
| + // It should clear the map even if some keys are not equal to themselves. |
| + void clear(); |
| + |
| + void forEach(void action(K key, V value)) { |
| + for (K key in keys) { |
| + action(key, this[key]); |
| + } |
| + } |
| + |
| + void addAll(Map<K, V> other) { |
| + for (K key in other.keys) { |
| + this[key] = other[key]; |
| + } |
| + } |
| + |
| + bool containsValue(V value) { |
| + for (K key in keys) { |
| + if (this[key] == value) return true; |
| + } |
| + return false; |
| + } |
| + |
| + V putIfAbsent(K key, V ifAbsent()) { |
| + if (keys.contains(key)) { |
| + return this[key]; |
| + } |
| + return this[key] = ifAbsent(); |
| + } |
| + |
| + bool containsKey(Object key) => keys.contains(key); |
| + int get length => keys.length; |
| + bool get isEmpty => keys.isEmpty; |
| + bool get isNotEmpty => keys.isNotEmpty; |
| + Iterable<V> get values => new MapBaseValueIterable<V>(this); |
| + String toString() => Maps.mapToString(this); |
| +} |
| + |
| +/** |
| + * Basic implementation of an unmodifiable [Map]. |
| + * |
| + * This class has a basic implementation of all but two of the members of |
| + * an umodifiable [Map]. |
| + * A simple unmodifiable `Map` class can be implemented by extending this |
| + * class and implementing `keys` and `operator[]`. |
| + * |
| + * Modifying operations throw when used. |
| + * The remaining non-modifying operations are implemented in terms of `keys` |
| + * and `operator[]`. |
| + * |
| + * The `keys` iterable should have efficient [length] and [contains] |
| + * operations, and it should catch concurrent modifications of the keys |
| + * while iterating. |
| + * |
| + * A more efficient implementation is usually possible by also overriding |
| + * some of the other members as well. |
| + */ |
| +class UnmodifiableMapBase<K, V> = MapBase<K, V> with UnmodifiableMapMixin<K, V>; |
| + |
| +/** |
| + * Implementation of [Map.values] based on the map and its [Map.keys] iterable. |
| + * |
| + * Iterable that iterates over the values of a `Map`. |
| + * It accesses the values by iterating over the keys of the map, and using the |
| + * map's `operator[]` to lookup the keys. |
| + */ |
| +class MapBaseValueIterable<V> extends IterableBase<V> |
|
floitsch
2014/03/25 21:03:18
Do we need to make this public?
Lasse Reichstein Nielsen
2014/03/26 10:25:20
No. I've made this, the iterator and the mixin pri
|
| + implements EfficientLength { |
| + final Map _map; |
| + MapBaseValueIterable(this._map); |
| + |
| + int get length => _map.length; |
| + bool get isEmpty => _map.isEmpty; |
| + bool get isNotEmpty => _map.isNotEmpty; |
| + V get first => _map[_map.keys.first]; |
| + V get single => _map[_map.keys.single]; |
| + V get last => _map[_map.keys.last]; |
| + |
| + Iterator<V> get iterator => new MapBaseValueIterator<V>(_map); |
| +} |
| + |
| +/** |
| + * Iterator created by [MapBaseValueIterable]. |
| + * |
| + * Iterates over the values of a map by iterating its keys and lookup up the |
| + * values. |
| + */ |
| +class MapBaseValueIterator<V> implements Iterator<V> { |
|
floitsch
2014/03/25 21:03:18
ditto.
Lasse Reichstein Nielsen
2014/03/26 10:25:20
Done.
|
| + final Iterator _keys; |
| + final Map _map; |
| + V _current = null; |
| + |
| + MapBaseValueIterator(Map map) : _map = map, _keys = map.keys.iterator; |
| + |
| + bool moveNext() { |
| + if (_keys.moveNext()) { |
| + _current = _map[_keys.current]; |
| + return true; |
| + } |
| + _current = null; |
| + return false; |
| + } |
| + |
| + V get current => _current; |
| +} |
| + |
| +/** |
| + * Mixin that overrides mutating map operations with implementations that throw. |
| + */ |
| +class UnmodifiableMapMixin<K, V> implements Map<K, V> { |
|
floitsch
2014/03/25 21:03:18
I know this comes from pkg:collection where I revi
Lasse Reichstein Nielsen
2014/03/26 10:25:20
This is now private, so it's only used internally.
|
| + void operator[]=(K key, V value) { |
| + throw new UnsupportedError("Cannot modify unmodifiable map"); |
| + } |
| + void addAll(Map<K, V> other) { |
| + throw new UnsupportedError("Cannot modify unmodifiable map"); |
| + } |
| + void clear() { |
| + throw new UnsupportedError("Cannot modify unmodifiable map"); |
| + } |
| + V remove(Object key) { |
| + throw new UnsupportedError("Cannot modify unmodifiable map"); |
| + } |
| + V putIfAbsent(K key, V ifAbsent()) { |
| + throw new UnsupportedError("Cannot modify unmodifiable map"); |
| + } |
| +} |
| + |
| +/** |
| + * Wrapper around a class that implements [Map] that only exposes `Map` members. |
| + * |
| + * A simple wrapper that delegates all `Map` members to the map provided in the |
| + * constructor. |
| + * |
| + * Base for delegating map implementations like [UnmodifiableMapView]. |
| + */ |
| +class MapView<K, V> implements Map<K, V> { |
| + final Map<K, V> _map; |
| + MapView(Map<K, V> map) : _map = map; |
| + |
| + V operator[](Object key) => _map[key]; |
| + void operator[]=(K key, V value) { _map[key] = value; } |
| + void addAll(Map<K, V> other) { _map.addAll(other); } |
| + void clear() { _map.clear(); } |
| + V putIfAbsent(K key, V ifAbsent()) => _map.putIfAbsent(key, ifAbsent); |
| + bool containsKey(Object key) => _map.containsKey(key); |
| + bool containsValue(Object value) => _map.containsValue(value); |
| + void forEach(void action(K key, V value)) { _map.forEach(action); } |
| + bool get isEmpty => _map.isEmpty; |
| + bool get isNotEmpty => _map.isNotEmpty; |
| + int get length => _map.length; |
| + Iterable<K> get keys => _map.keys; |
| + V remove(Object key) => _map.remove(key); |
| + String toString() => _map.toString(); |
| + Iterable<V> get values => _map.values; |
| +} |
| + |
| +/** |
| + * View of a [Map] that disallow modifying the map. |
| + * |
| + * A wrapper around a `Map` that forwards all members to the map provided in |
| + * the constructor, except for operations that modify the map. |
| + * Modifying operations throw instead. |
| + */ |
| +class UnmodifiableMapView<K, V> = MapView<K, V> with UnmodifiableMapMixin<K, V>; |
| + |
| +/** |
| * Helper class which implements complex [Map] operations |
| * in term of basic ones ([Map.keys], [Map.operator []], |
| * [Map.operator []=] and [Map.remove].) Not all methods are |