Chromium Code Reviews| Index: pkg/collection/lib/wrappers.dart |
| diff --git a/pkg/collection/lib/wrappers.dart b/pkg/collection/lib/wrappers.dart |
| index 0fcc8c23e80a42f6e86c84ebea3988f512cfca02..cd4da3f8ac59677202cb557932339867bf801724 100644 |
| --- a/pkg/collection/lib/wrappers.dart |
| +++ b/pkg/collection/lib/wrappers.dart |
| @@ -19,19 +19,15 @@ export "dart:collection" show UnmodifiableListView; |
| part "src/unmodifiable_wrappers.dart"; |
| /** |
| - * Creates an [Iterable] that delegates all operations to a base iterable. |
| + * A base class for delegating iterables. |
| * |
| - * This class can be used hide non-`Iterable` methods of an iterable object, |
| - * or it can be extended to add extra functionality on top of an existing |
| - * iterable object. |
| + * Subclasses can provide a [_base] that should be delegated to. Unlike |
| + * [DelegatingIterable], this allows the base to be created on demand. |
| */ |
| -class DelegatingIterable<E> implements Iterable<E> { |
| - final Iterable<E> _base; |
| +abstract class _DelegatingIterableBase<E> implements Iterable<E> { |
| + Iterable<E> get _base; |
| - /** |
| - * Create a wrapper that forwards operations to [base]. |
| - */ |
| - const DelegatingIterable(Iterable<E> base) : _base = base; |
| + const _DelegatingIterableBase(); |
| bool any(bool test(E element)) => _base.any(test); |
| @@ -93,6 +89,22 @@ class DelegatingIterable<E> implements Iterable<E> { |
| String toString() => _base.toString(); |
| } |
| +/** |
| + * Creates an [Iterable] that delegates all operations to a base iterable. |
| + * |
| + * This class can be used hide non-`Iterable` methods of an iterable object, |
| + * or it can be extended to add extra functionality on top of an existing |
| + * iterable object. |
| + */ |
| +class DelegatingIterable<E> extends _DelegatingIterableBase<E> { |
| + final Iterable<E> _base; |
| + |
| + /** |
| + * Create a wrapper that forwards operations to [base]. |
| + */ |
| + const DelegatingIterable(Iterable<E> base) : _base = base; |
| +} |
| + |
| /** |
| * Creates a [List] that delegates all operations to a base list. |
| @@ -337,3 +349,129 @@ class DelegatingMap<K, V> implements Map<K, V> { |
| String toString() => _base.toString(); |
| } |
| + |
| +/** |
| + * Creates an unmodifiable [Set] that delegates all operations to a base map's |
| + * keys. |
| + * |
| + * This class can be used to make a `Map` look like a `Set`. Note that [lookup] |
| + * is not `O(1)` for this set. |
| + */ |
| +class MapKeySet<E> extends _DelegatingIterableBase<E> |
| + with UnmodifiableSetMixin<E> { |
| + final Map<E, dynamic> _baseMap; |
| + |
| + Iterable<E> get _base => _baseMap.keys; |
| + |
| + MapKeySet(Map<E, dynamic> base) : _baseMap = base; |
| + |
| + bool contains(Object element) => _baseMap.containsKey(element); |
| + |
| + bool get isEmpty => _baseMap.isEmpty; |
| + |
| + bool get isNotEmpty => _baseMap.isNotEmpty; |
| + |
| + int get length => _baseMap.length; |
| + |
| + String toString() => toSet().toString(); |
| + |
| + bool containsAll(Iterable<Object> other) => other.every(contains); |
| + |
| + Set<E> difference(Set<E> other) => |
| + where((element) => !other.contains(element)).toSet(); |
| + |
| + Set<E> intersection(Set<Object> other) => |
| + where((element) => other.contains(element)).toSet(); |
| + |
| + E lookup(E element) => firstWhere((key) => element == key, |
| + orElse: () => null); |
| + |
| + Set<E> union(Set<E> other) => toSet()..addAll(other); |
| +} |
| + |
| +/** |
| + * Creates a [Set] that delegates all operations to a base map's values. |
| + * |
| + * This class can be used to make a `Map` whose keys are determinable from its |
|
kevmoo
2014/05/08 20:40:15
I'm a bit confused by this sentence. What's the us
nweiz
2014/05/08 21:14:56
See my comment on the issue: https://code.google.c
kevmoo
2014/05/08 23:01:53
Your comment makes the usage clear, but the docs h
nweiz
2014/05/09 02:48:50
Done.
|
| + * values look like a `Set`. |
| + */ |
| +class MapValueSet<K, V> extends _DelegatingIterableBase<V> implements Set<V> { |
| + final Map<K, V> _baseMap; |
| + final Function _keyForValue; |
| + |
| + Iterable<V> get _base => _baseMap.values; |
| + |
| + /** |
| + * Creates a new [MapValueSet] based on [base]. |
| + * |
| + * [keyForValue] returns the key in the map that should be associated with the |
| + * given value. The set's notion of equality is identical to the equality of |
| + * the return values of [keyForValue]. |
| + */ |
| + MapValueSet(Map<K, V> base, K keyForValue(V value)) |
| + : _baseMap = base, |
| + _keyForValue = keyForValue; |
| + |
| + bool contains(Object element) { |
| + if (element is! V) return false; |
| + return _baseMap.containsKey(_keyForValue(element)); |
| + } |
| + |
| + bool get isEmpty => _baseMap.isEmpty; |
| + |
| + bool get isNotEmpty => _baseMap.isNotEmpty; |
| + |
| + int get length => _baseMap.length; |
| + |
| + String toString() => toSet().toString(); |
| + |
| + bool add(V value) { |
| + var key = _keyForValue(value); |
| + if (_baseMap.containsKey(key)) return false; |
| + _baseMap[key] = value; |
| + return true; |
| + } |
| + |
| + void addAll(Iterable<V> elements) => elements.forEach(add); |
| + |
| + void clear() => _baseMap.clear(); |
| + |
| + bool containsAll(Iterable<Object> other) => other.every(contains); |
| + |
| + Set<V> difference(Set<V> other) => |
| + where((element) => !other.contains(element)).toSet(); |
| + |
| + Set<V> intersection(Set<Object> other) => |
| + where((element) => other.contains(element)).toSet(); |
| + |
| + V lookup(V element) => _baseMap[_keyForValue(element)]; |
| + |
| + bool remove(Object value) { |
| + if (value is! V) return false; |
| + var key = _keyForValue(value); |
| + if (!_baseMap.containsKey(key)) return false; |
| + _baseMap.remove(key); |
| + return true; |
| + } |
| + |
| + void removeAll(Iterable<Object> elements) => elements.forEach(remove); |
| + |
| + void removeWhere(bool test(V element)) { |
| + new Map.from(_baseMap).forEach((key, value) { |
| + if (test(value)) remove(key); |
| + }); |
| + } |
| + |
| + void retainAll(Iterable<Object> elements) { |
| + var retainKeys = elements.where((element) => element is V) |
| + .map((element) => _keyForValue(element)).toSet(); |
| + new Map.from(_baseMap).forEach((key, value) { |
| + if (!retainKeys.contains(key)) remove(key); |
| + }); |
| + } |
| + |
| + void retainWhere(bool test(V element)) => |
| + removeWhere((element) => !test(element)); |
| + |
| + Set<V> union(Set<V> other) => toSet()..addAll(other); |
| +} |