| OLD | NEW |
| 1 // Copyright 2013 Google Inc. All Rights Reserved. | 1 // Copyright 2013 Google Inc. All Rights Reserved. |
| 2 // | 2 // |
| 3 // Licensed under the Apache License, Version 2.0 (the "License"); | 3 // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 // you may not use this file except in compliance with the License. | 4 // you may not use this file except in compliance with the License. |
| 5 // You may obtain a copy of the License at | 5 // You may obtain a copy of the License at |
| 6 // | 6 // |
| 7 // http://www.apache.org/licenses/LICENSE-2.0 | 7 // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 // | 8 // |
| 9 // Unless required by applicable law or agreed to in writing, software | 9 // Unless required by applicable law or agreed to in writing, software |
| 10 // distributed under the License is distributed on an "AS IS" BASIS, | 10 // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 // See the License for the specific language governing permissions and | 12 // See the License for the specific language governing permissions and |
| 13 // limitations under the License. | 13 // limitations under the License. |
| 14 | 14 |
| 15 part of quiver.collection; | 15 part of quiver.collection; |
| 16 | 16 |
| 17 /** | 17 /// An associative container that maps a key to multiple values. |
| 18 * An associative container that maps a key to multiple values. | 18 /// |
| 19 * | 19 /// Key lookups return mutable collections that are views of the multimap. |
| 20 * Key lookups return mutable collections that are views of the multimap. | 20 /// Updates to the multimap are reflected in these collections and similarly, |
| 21 * Updates to the multimap are reflected in these collections and similarly, | 21 /// modifications to the returned collections are reflected in the multimap. |
| 22 * modifications to the returned collections are reflected in the multimap. | |
| 23 */ | |
| 24 abstract class Multimap<K, V> { | 22 abstract class Multimap<K, V> { |
| 25 /** | 23 /// Constructs a new list-backed multimap. |
| 26 * Constructs a new list-backed multimap. | |
| 27 */ | |
| 28 factory Multimap() => new ListMultimap<K, V>(); | 24 factory Multimap() => new ListMultimap<K, V>(); |
| 29 | 25 |
| 30 /** | 26 /// Constructs a new list-backed multimap. For each element e of [iterable], |
| 31 * Returns whether this multimap contains the given [value]. | 27 /// adds an association from [key](e) to [value](e). [key] and [value] each |
| 32 */ | 28 /// default to the identity function. |
| 29 factory Multimap.fromIterable(Iterable iterable, |
| 30 {K key(element), V value(element)}) = ListMultimap<K, V>.fromIterable; |
| 31 |
| 32 /// Returns whether this multimap contains the given [value]. |
| 33 bool containsValue(Object value); | 33 bool containsValue(Object value); |
| 34 | 34 |
| 35 /** | 35 /// Returns whether this multimap contains the given [key]. |
| 36 * Returns whether this multimap contains the given [key]. | |
| 37 */ | |
| 38 bool containsKey(Object key); | 36 bool containsKey(Object key); |
| 39 | 37 |
| 40 /** | 38 /// Returns the values for the given [key]. An empty iterable is returned if |
| 41 * Returns the values for the given [key]. An empty iterable is returned if | 39 /// [key] is not mapped. The returned collection is a view on the multimap. |
| 42 * [key] is not mapped. The returned collection is a view on the multimap. | 40 /// Updates to the collection modify the multimap and likewise, modifications |
| 43 * Updates to the collection modify the multimap and likewise, modifications | 41 /// to the multimap are reflected in the returned collection. |
| 44 * to the multimap are reflected in the returned collection. | |
| 45 */ | |
| 46 Iterable<V> operator [](Object key); | 42 Iterable<V> operator [](Object key); |
| 47 | 43 |
| 48 /** | 44 /// Adds an association from the given key to the given value. |
| 49 * Adds an association from the given key to the given value. | |
| 50 */ | |
| 51 void add(K key, V value); | 45 void add(K key, V value); |
| 52 | 46 |
| 53 /** | 47 /// Adds an association from the given key to each of the given values. |
| 54 * Adds an association from the given key to each of the given values. | |
| 55 */ | |
| 56 void addValues(K key, Iterable<V> values); | 48 void addValues(K key, Iterable<V> values); |
| 57 | 49 |
| 58 /** | 50 /// Adds all associations of [other] to this multimap. |
| 59 * Adds all associations of [other] to this multimap. | 51 /// |
| 60 * | 52 /// The operation is equivalent to doing `this[key] = value` for each key and |
| 61 * The operation is equivalent to doing `this[key] = value` for each key | 53 /// associated value in other. It iterates over [other], which must therefore |
| 62 * and associated value in other. It iterates over [other], which must | 54 /// not change during the iteration. |
| 63 * therefore not change during the iteration. | |
| 64 */ | |
| 65 void addAll(Multimap<K, V> other); | 55 void addAll(Multimap<K, V> other); |
| 66 | 56 |
| 67 /** | 57 /// Removes the association between the given [key] and [value]. Returns |
| 68 * Removes the association between the given [key] and [value]. Returns | 58 /// `true` if the association existed, `false` otherwise. |
| 69 * `true` if the association existed, `false` otherwise. | |
| 70 */ | |
| 71 bool remove(Object key, V value); | 59 bool remove(Object key, V value); |
| 72 | 60 |
| 73 /** | 61 /// Removes the association for the given [key]. Returns the collection of |
| 74 * Removes the association for the given [key]. Returns the collection of | 62 /// removed values, or an empty iterable if [key] was unmapped. |
| 75 * removed values, or an empty iterable if [key] was unmapped. | |
| 76 */ | |
| 77 Iterable<V> removeAll(Object key); | 63 Iterable<V> removeAll(Object key); |
| 78 | 64 |
| 79 /** | 65 /// Removes all data from the multimap. |
| 80 * Removes all data from the multimap. | |
| 81 */ | |
| 82 void clear(); | 66 void clear(); |
| 83 | 67 |
| 84 /** | 68 /// Applies [f] to each {key, Iterable<value>} pair of the multimap. |
| 85 * Applies [f] to each {key, Iterable<value>} pair of the multimap. | 69 /// |
| 86 * | 70 /// It is an error to add or remove keys from the map during iteration. |
| 87 * It is an error to add or remove keys from the map during iteration. | |
| 88 */ | |
| 89 void forEachKey(void f(K key, Iterable<V> value)); | 71 void forEachKey(void f(K key, Iterable<V> value)); |
| 90 | 72 |
| 91 /** | 73 /// Applies [f] to each {key, value} pair of the multimap. |
| 92 * Applies [f] to each {key, value} pair of the multimap. | 74 /// |
| 93 * | 75 /// It is an error to add or remove keys from the map during iteration. |
| 94 * It is an error to add or remove keys from the map during iteration. | |
| 95 */ | |
| 96 void forEach(void f(K key, V value)); | 76 void forEach(void f(K key, V value)); |
| 97 | 77 |
| 98 /** | 78 /// The keys of [this]. |
| 99 * The keys of [this]. | |
| 100 */ | |
| 101 Iterable<K> get keys; | 79 Iterable<K> get keys; |
| 102 | 80 |
| 103 /** | 81 /// The values of [this]. |
| 104 * The values of [this]. | |
| 105 */ | |
| 106 Iterable<V> get values; | 82 Iterable<V> get values; |
| 107 | 83 |
| 108 /** | 84 /// Returns a view of this multimap as a map. |
| 109 * Returns a view of this multimap as a map. | |
| 110 */ | |
| 111 Map<K, Iterable<V>> asMap(); | 85 Map<K, Iterable<V>> asMap(); |
| 112 | 86 |
| 113 /** | 87 /// The number of keys in the multimap. |
| 114 * Returns a view of this multimap as a map. | |
| 115 * | |
| 116 * DEPRECATED: this method is replaced with `asMap`. | |
| 117 */ | |
| 118 @Deprecated('Will be removed in 0.22.0') | |
| 119 Map<K, Iterable<V>> toMap(); | |
| 120 | |
| 121 /** | |
| 122 * The number of keys in the multimap. | |
| 123 */ | |
| 124 int get length; | 88 int get length; |
| 125 | 89 |
| 126 /** | 90 /// Returns true if there is no key in the multimap. |
| 127 * Returns true if there is no key in the multimap. | |
| 128 */ | |
| 129 bool get isEmpty; | 91 bool get isEmpty; |
| 130 | 92 |
| 131 /** | 93 /// Returns true if there is at least one key in the multimap. |
| 132 * Returns true if there is at least one key in the multimap. | |
| 133 */ | |
| 134 bool get isNotEmpty; | 94 bool get isNotEmpty; |
| 135 } | 95 } |
| 136 | 96 |
| 137 /** | 97 /// Abstract base class for multimap implementations. |
| 138 * Abstract base class for multimap implementations. | |
| 139 */ | |
| 140 abstract class _BaseMultimap<K, V, C extends Iterable<V>> | 98 abstract class _BaseMultimap<K, V, C extends Iterable<V>> |
| 141 implements Multimap<K, V> { | 99 implements Multimap<K, V> { |
| 142 final Map<K, Iterable<V>> _map = new HashMap(); | 100 static T _id<T>(x) => x; |
| 143 | 101 |
| 144 Iterable<V> _create(); | 102 _BaseMultimap(); |
| 103 |
| 104 /// Constructs a new multimap. For each element e of [iterable], adds an |
| 105 /// association from [key](e) to [value](e). [key] and [value] each default |
| 106 /// to the identity function. |
| 107 _BaseMultimap.fromIterable(Iterable iterable, |
| 108 {K key(element), V value(element)}) { |
| 109 key ??= _id; |
| 110 value ??= _id; |
| 111 for (var element in iterable) { |
| 112 add(key(element), value(element)); |
| 113 } |
| 114 } |
| 115 |
| 116 final Map<K, C> _map = new HashMap(); |
| 117 |
| 118 C _create(); |
| 145 void _add(C iterable, V value); | 119 void _add(C iterable, V value); |
| 146 void _addAll(C iterable, Iterable<V> value); | 120 void _addAll(C iterable, Iterable<V> value); |
| 147 void _clear(C iterable); | 121 void _clear(C iterable); |
| 148 bool _remove(C iterable, Object value); | 122 bool _remove(C iterable, Object value); |
| 149 Iterable<V> _wrap(Object key, C iterable); | 123 Iterable<V> _wrap(Object key, C iterable); |
| 150 | 124 |
| 151 bool containsValue(Object value) => values.contains(value); | 125 bool containsValue(Object value) => values.contains(value); |
| 152 bool containsKey(Object key) => _map.keys.contains(key); | 126 bool containsKey(Object key) => _map.keys.contains(key); |
| 153 | 127 |
| 154 Iterable<V> operator [](Object key) { | 128 Iterable<V> operator [](Object key) { |
| 155 var values = _map[key]; | 129 var values = _map[key]; |
| 156 if (values == null) { | 130 if (values == null) { |
| 157 values = _create(); | 131 values = _create(); |
| 158 } | 132 } |
| 159 return _wrap(key, values); | 133 return _wrap(key, values); |
| 160 } | 134 } |
| 161 | 135 |
| 162 void add(K key, V value) { | 136 void add(K key, V value) { |
| 163 _map.putIfAbsent(key, _create); | 137 _map.putIfAbsent(key, _create); |
| 164 _add(_map[key], value); | 138 _add(_map[key], value); |
| 165 } | 139 } |
| 166 | 140 |
| 167 void addValues(K key, Iterable<V> values) { | 141 void addValues(K key, Iterable<V> values) { |
| 168 _map.putIfAbsent(key, _create); | 142 _map.putIfAbsent(key, _create); |
| 169 _addAll(_map[key], values); | 143 _addAll(_map[key], values); |
| 170 } | 144 } |
| 171 | 145 |
| 172 /** | 146 /// Adds all associations of [other] to this multimap. |
| 173 * Adds all associations of [other] to this multimap. | 147 /// |
| 174 * | 148 /// The operation is equivalent to doing `this[key] = value` for each key and |
| 175 * The operation is equivalent to doing `this[key] = value` for each key | 149 /// associated value in other. It iterates over [other], which must therefore |
| 176 * and associated value in other. It iterates over [other], which must | 150 /// not change during the iteration. |
| 177 * therefore not change during the iteration. | 151 /// |
| 178 * | 152 /// This implementation iterates through each key of [other] and adds the |
| 179 * This implementation iterates through each key of [other] and adds the | 153 /// associated values to this instance via [addValues]. |
| 180 * associated values to this instance via [addValues]. | |
| 181 */ | |
| 182 void addAll(Multimap<K, V> other) => other.forEachKey(addValues); | 154 void addAll(Multimap<K, V> other) => other.forEachKey(addValues); |
| 183 | 155 |
| 184 bool remove(Object key, V value) { | 156 bool remove(Object key, V value) { |
| 185 if (!_map.containsKey(key)) return false; | 157 if (!_map.containsKey(key)) return false; |
| 186 bool removed = _remove(_map[key], value); | 158 bool removed = _remove(_map[key], value); |
| 187 if (removed && _map[key].isEmpty) _map.remove(key); | 159 if (removed && _map[key].isEmpty) _map.remove(key); |
| 188 return removed; | 160 return removed; |
| 189 } | 161 } |
| 190 | 162 |
| 191 Iterable<V> removeAll(Object key) { | 163 Iterable<V> removeAll(Object key) { |
| 192 // Cast to dynamic to remove warnings | 164 // Cast to dynamic to remove warnings |
| 193 var values = _map.remove(key) as dynamic; | 165 var values = _map.remove(key) as dynamic; |
| 194 var retValues = _create() as dynamic; | 166 var retValues = _create() as dynamic; |
| 195 if (values != null) { | 167 if (values != null) { |
| 196 retValues.addAll(values); | 168 retValues.addAll(values); |
| 197 values.clear(); | 169 values.clear(); |
| 198 } | 170 } |
| 199 return retValues; | 171 return retValues as Iterable<V>; |
| 200 } | 172 } |
| 201 | 173 |
| 202 void clear() { | 174 void clear() { |
| 203 _map.forEach((K key, Iterable<V> value) => _clear(value)); | 175 _map.forEach((K key, Iterable<V> value) => _clear(value)); |
| 204 _map.clear(); | 176 _map.clear(); |
| 205 } | 177 } |
| 206 | 178 |
| 207 void forEachKey(void f(K key, Iterable<V> value)) => _map.forEach(f); | 179 void forEachKey(void f(K key, C value)) => _map.forEach(f); |
| 208 | 180 |
| 209 void forEach(void f(K key, V value)) { | 181 void forEach(void f(K key, V value)) { |
| 210 _map.forEach((K key, Iterable<V> values) { | 182 _map.forEach((K key, Iterable<V> values) { |
| 211 values.forEach((V value) => f(key, value)); | 183 values.forEach((V value) => f(key, value)); |
| 212 }); | 184 }); |
| 213 } | 185 } |
| 214 | 186 |
| 215 Iterable<K> get keys => _map.keys; | 187 Iterable<K> get keys => _map.keys; |
| 216 Iterable<V> get values => _map.values.expand((x) => x); | 188 Iterable<V> get values => _map.values.expand((x) => x); |
| 217 Iterable<Iterable<V>> get _groupedValues => _map.values; | 189 Iterable<Iterable<V>> get _groupedValues => _map.values; |
| 218 int get length => _map.length; | 190 int get length => _map.length; |
| 219 bool get isEmpty => _map.isEmpty; | 191 bool get isEmpty => _map.isEmpty; |
| 220 bool get isNotEmpty => _map.isNotEmpty; | 192 bool get isNotEmpty => _map.isNotEmpty; |
| 221 } | 193 } |
| 222 | 194 |
| 223 /** | 195 /// A multimap implementation that uses [List]s to store the values associated |
| 224 * A multimap implementation that uses [List]s to store the values associated | 196 /// with each key. |
| 225 * with each key. | |
| 226 */ | |
| 227 class ListMultimap<K, V> extends _BaseMultimap<K, V, List<V>> { | 197 class ListMultimap<K, V> extends _BaseMultimap<K, V, List<V>> { |
| 228 ListMultimap() : super(); | 198 ListMultimap(); |
| 199 |
| 200 /// Constructs a new list-backed multimap. For each element e of [iterable], |
| 201 /// adds an association from [key](e) to [value](e). [key] and [value] each |
| 202 /// default to the identity function. |
| 203 ListMultimap.fromIterable(Iterable iterable, |
| 204 {K key(element), V value(element)}) |
| 205 : super.fromIterable(iterable, key: key, value: value); |
| 206 |
| 229 @override | 207 @override |
| 230 List<V> _create() => new List<V>(); | 208 List<V> _create() => new List<V>(); |
| 231 @override | 209 @override |
| 232 void _add(List<V> iterable, V value) { | 210 void _add(List<V> iterable, V value) { |
| 233 iterable.add(value); | 211 iterable.add(value); |
| 234 } | 212 } |
| 213 |
| 235 @override | 214 @override |
| 236 void _addAll(List<V> iterable, Iterable<V> value) => iterable.addAll(value); | 215 void _addAll(List<V> iterable, Iterable<V> value) => iterable.addAll(value); |
| 237 @override | 216 @override |
| 238 void _clear(List<V> iterable) => iterable.clear(); | 217 void _clear(List<V> iterable) => iterable.clear(); |
| 239 @override | 218 @override |
| 240 bool _remove(List<V> iterable, Object value) => iterable.remove(value); | 219 bool _remove(List<V> iterable, Object value) => iterable.remove(value); |
| 241 @override | 220 @override |
| 242 List<V> _wrap(Object key, List<V> iterable) => | 221 List<V> _wrap(Object key, List<V> iterable) => |
| 243 new _WrappedList(_map, key, iterable); | 222 new _WrappedList(_map, key, iterable); |
| 244 List<V> operator [](Object key) => super[key]; | 223 List<V> operator [](Object key) => super[key]; |
| 245 List<V> removeAll(Object key) => super.removeAll(key); | 224 List<V> removeAll(Object key) => super.removeAll(key); |
| 246 Map<K, List<V>> asMap() => new _WrappedMap<K, V, List<V>>(this); | 225 Map<K, List<V>> asMap() => new _WrappedMap<K, V, List<V>>(this); |
| 247 @Deprecated('Will be removed in 0.22.0') | |
| 248 Map<K, List<V>> toMap() => asMap(); | |
| 249 } | 226 } |
| 250 | 227 |
| 251 /** | 228 /// A multimap implementation that uses [Set]s to store the values associated |
| 252 * A multimap implementation that uses [Set]s to store the values associated | 229 /// with each key. |
| 253 * with each key. | |
| 254 */ | |
| 255 class SetMultimap<K, V> extends _BaseMultimap<K, V, Set<V>> { | 230 class SetMultimap<K, V> extends _BaseMultimap<K, V, Set<V>> { |
| 256 SetMultimap() : super(); | 231 SetMultimap(); |
| 232 |
| 233 /// Constructs a new set-backed multimap. For each element e of [iterable], |
| 234 /// adds an association from [key](e) to [value](e). [key] and [value] each |
| 235 /// default to the identity function. |
| 236 SetMultimap.fromIterable(Iterable iterable, |
| 237 {K key(element), V value(element)}) |
| 238 : super.fromIterable(iterable, key: key, value: value); |
| 239 |
| 257 @override | 240 @override |
| 258 Set<V> _create() => new Set<V>(); | 241 Set<V> _create() => new Set<V>(); |
| 259 @override | 242 @override |
| 260 void _add(Set<V> iterable, V value) { | 243 void _add(Set<V> iterable, V value) { |
| 261 iterable.add(value); | 244 iterable.add(value); |
| 262 } | 245 } |
| 246 |
| 263 @override | 247 @override |
| 264 void _addAll(Set<V> iterable, Iterable<V> value) => iterable.addAll(value); | 248 void _addAll(Set<V> iterable, Iterable<V> value) => iterable.addAll(value); |
| 265 @override | 249 @override |
| 266 void _clear(Set<V> iterable) => iterable.clear(); | 250 void _clear(Set<V> iterable) => iterable.clear(); |
| 267 @override | 251 @override |
| 268 bool _remove(Set<V> iterable, Object value) => iterable.remove(value); | 252 bool _remove(Set<V> iterable, Object value) => iterable.remove(value); |
| 269 @override | 253 @override |
| 270 Set<V> _wrap(Object key, Iterable<V> iterable) => | 254 Set<V> _wrap(Object key, Iterable<V> iterable) => |
| 271 new _WrappedSet(_map, key, iterable); | 255 new _WrappedSet(_map, key, iterable); |
| 272 Set<V> operator [](Object key) => super[key]; | 256 Set<V> operator [](Object key) => super[key]; |
| 273 Set<V> removeAll(Object key) => super.removeAll(key); | 257 Set<V> removeAll(Object key) => super.removeAll(key); |
| 274 Map<K, Set<V>> asMap() => new _WrappedMap<K, V, Set<V>>(this); | 258 Map<K, Set<V>> asMap() => new _WrappedMap<K, V, Set<V>>(this); |
| 275 @Deprecated('Will be removed in 0.22.0') | |
| 276 Map<K, Set<V>> toMap() => asMap(); | |
| 277 } | 259 } |
| 278 | 260 |
| 279 /** | 261 /// A [Map] that delegates its operations to an underlying multimap. |
| 280 * A [Map] that delegates its operations to an underlying multimap. | |
| 281 */ | |
| 282 class _WrappedMap<K, V, C extends Iterable<V>> implements Map<K, C> { | 262 class _WrappedMap<K, V, C extends Iterable<V>> implements Map<K, C> { |
| 283 final _BaseMultimap<K, V, C> _multimap; | 263 final _BaseMultimap<K, V, C> _multimap; |
| 284 | 264 |
| 285 _WrappedMap(this._multimap); | 265 _WrappedMap(this._multimap); |
| 286 | 266 |
| 287 C operator [](Object key) => _multimap[key]; | 267 C operator [](Object key) => _multimap[key]; |
| 288 | 268 |
| 289 void operator []=(K key, C value) { | 269 void operator []=(K key, C value) { |
| 290 throw new UnsupportedError("Insert unsupported on map view"); | 270 throw new UnsupportedError("Insert unsupported on map view"); |
| 291 } | 271 } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 303 bool containsValue(Object value) => _multimap.containsValue(value); | 283 bool containsValue(Object value) => _multimap.containsValue(value); |
| 304 void forEach(void f(K key, C value)) => _multimap.forEachKey(f); | 284 void forEach(void f(K key, C value)) => _multimap.forEachKey(f); |
| 305 bool get isEmpty => _multimap.isEmpty; | 285 bool get isEmpty => _multimap.isEmpty; |
| 306 bool get isNotEmpty => _multimap.isNotEmpty; | 286 bool get isNotEmpty => _multimap.isNotEmpty; |
| 307 Iterable<K> get keys => _multimap.keys; | 287 Iterable<K> get keys => _multimap.keys; |
| 308 int get length => _multimap.length; | 288 int get length => _multimap.length; |
| 309 C remove(Object key) => _multimap.removeAll(key); | 289 C remove(Object key) => _multimap.removeAll(key); |
| 310 Iterable<C> get values => _multimap._groupedValues; | 290 Iterable<C> get values => _multimap._groupedValues; |
| 311 } | 291 } |
| 312 | 292 |
| 313 /** | 293 /// Iterable wrapper that syncs to an underlying map. |
| 314 * Iterable wrapper that syncs to an underlying map. | |
| 315 */ | |
| 316 class _WrappedIterable<K, V, C extends Iterable<V>> implements Iterable<V> { | 294 class _WrappedIterable<K, V, C extends Iterable<V>> implements Iterable<V> { |
| 317 final K _key; | 295 final K _key; |
| 318 final Map<K, C> _map; | 296 final Map<K, C> _map; |
| 319 C _delegate; | 297 C _delegate; |
| 320 | 298 |
| 321 _WrappedIterable(this._map, this._key, this._delegate); | 299 _WrappedIterable(this._map, this._key, this._delegate); |
| 322 | 300 |
| 323 _addToMap() => _map[_key] = _delegate; | 301 _addToMap() => _map[_key] = _delegate; |
| 324 | 302 |
| 325 /** | 303 /// Ensures we hold an up-to-date delegate. In the case where all mappings |
| 326 * Ensures we hold an up-to-date delegate. In the case where all mappings for | 304 /// for _key are removed from the multimap, the Iterable referenced by |
| 327 * _key are removed from the multimap, the Iterable referenced by _delegate is | 305 /// _delegate is removed from the underlying map. At that point, any new |
| 328 * removed from the underlying map. At that point, any new addition via the | 306 /// addition via the multimap triggers the creation of a new Iterable, and |
| 329 * multimap triggers the creation of a new Iterable, and the empty delegate | 307 /// the empty delegate we hold would be stale. As such, we check the |
| 330 * we hold would be stale. As such, we check the underlying map and update | 308 /// underlying map and update our delegate when the one we hold is empty. |
| 331 * our delegate when the one we hold is empty. | |
| 332 */ | |
| 333 _syncDelegate() { | 309 _syncDelegate() { |
| 334 if (_delegate.isEmpty) { | 310 if (_delegate.isEmpty) { |
| 335 var updated = _map[_key]; | 311 var updated = _map[_key]; |
| 336 if (updated != null) { | 312 if (updated != null) { |
| 337 _delegate = updated; | 313 _delegate = updated; |
| 338 } | 314 } |
| 339 } | 315 } |
| 340 } | 316 } |
| 341 | 317 |
| 342 bool any(bool test(V element)) { | 318 bool any(bool test(V element)) { |
| 343 _syncDelegate(); | 319 _syncDelegate(); |
| 344 return _delegate.any(test); | 320 return _delegate.any(test); |
| 345 } | 321 } |
| 346 | 322 |
| 347 bool contains(Object element) { | 323 bool contains(Object element) { |
| 348 _syncDelegate(); | 324 _syncDelegate(); |
| 349 return _delegate.contains(element); | 325 return _delegate.contains(element); |
| 350 } | 326 } |
| 351 | 327 |
| 352 V elementAt(int index) { | 328 V elementAt(int index) { |
| 353 _syncDelegate(); | 329 _syncDelegate(); |
| 354 return _delegate.elementAt(index); | 330 return _delegate.elementAt(index); |
| 355 } | 331 } |
| 356 | 332 |
| 357 bool every(bool test(V element)) { | 333 bool every(bool test(V element)) { |
| 358 _syncDelegate(); | 334 _syncDelegate(); |
| 359 return _delegate.every(test); | 335 return _delegate.every(test); |
| 360 } | 336 } |
| 361 | 337 |
| 362 Iterable expand(Iterable f(V element)) { | 338 Iterable<T> expand<T>(Iterable<T> f(V element)) { |
| 363 _syncDelegate(); | 339 _syncDelegate(); |
| 364 return _delegate.expand(f); | 340 return _delegate.expand(f); |
| 365 } | 341 } |
| 366 | 342 |
| 367 V get first { | 343 V get first { |
| 368 _syncDelegate(); | 344 _syncDelegate(); |
| 369 return _delegate.first; | 345 return _delegate.first; |
| 370 } | 346 } |
| 371 | 347 |
| 372 V firstWhere(bool test(V element), {V orElse()}) { | 348 V firstWhere(bool test(V element), {V orElse()}) { |
| 373 _syncDelegate(); | 349 _syncDelegate(); |
| 374 return _delegate.firstWhere(test, orElse: orElse); | 350 return _delegate.firstWhere(test, orElse: orElse); |
| 375 } | 351 } |
| 376 | 352 |
| 377 fold(initialValue, combine(previousValue, V element)) { | 353 T fold<T>(T initialValue, T combine(T previousValue, V element)) { |
| 378 _syncDelegate(); | 354 _syncDelegate(); |
| 379 return _delegate.fold(initialValue, combine); | 355 return _delegate.fold(initialValue, combine); |
| 380 } | 356 } |
| 381 | 357 |
| 382 void forEach(void f(V element)) { | 358 void forEach(void f(V element)) { |
| 383 _syncDelegate(); | 359 _syncDelegate(); |
| 384 _delegate.forEach(f); | 360 _delegate.forEach(f); |
| 385 } | 361 } |
| 386 | 362 |
| 387 bool get isEmpty { | 363 bool get isEmpty { |
| (...skipping 24 matching lines...) Expand all Loading... |
| 412 V lastWhere(bool test(V element), {V orElse()}) { | 388 V lastWhere(bool test(V element), {V orElse()}) { |
| 413 _syncDelegate(); | 389 _syncDelegate(); |
| 414 return _delegate.lastWhere(test, orElse: orElse); | 390 return _delegate.lastWhere(test, orElse: orElse); |
| 415 } | 391 } |
| 416 | 392 |
| 417 int get length { | 393 int get length { |
| 418 _syncDelegate(); | 394 _syncDelegate(); |
| 419 return _delegate.length; | 395 return _delegate.length; |
| 420 } | 396 } |
| 421 | 397 |
| 422 Iterable map(f(V element)) { | 398 Iterable<T> map<T>(T f(V element)) { |
| 423 _syncDelegate(); | 399 _syncDelegate(); |
| 424 return _delegate.map(f); | 400 return _delegate.map(f); |
| 425 } | 401 } |
| 426 | 402 |
| 427 V reduce(V combine(V value, V element)) { | 403 V reduce(V combine(V value, V element)) { |
| 428 _syncDelegate(); | 404 _syncDelegate(); |
| 429 return _delegate.reduce(combine); | 405 return _delegate.reduce(combine); |
| 430 } | 406 } |
| 431 | 407 |
| 432 V get single { | 408 V get single { |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 475 } | 451 } |
| 476 | 452 |
| 477 Iterable<V> where(bool test(V element)) { | 453 Iterable<V> where(bool test(V element)) { |
| 478 _syncDelegate(); | 454 _syncDelegate(); |
| 479 return _delegate.where(test); | 455 return _delegate.where(test); |
| 480 } | 456 } |
| 481 } | 457 } |
| 482 | 458 |
| 483 class _WrappedList<K, V> extends _WrappedIterable<K, V, List<V>> | 459 class _WrappedList<K, V> extends _WrappedIterable<K, V, List<V>> |
| 484 implements List<V> { | 460 implements List<V> { |
| 485 _WrappedList(Map<K, List<V>> map, K key, List<V> delegate) | 461 _WrappedList(Map<K, Iterable<V>> map, K key, List<V> delegate) |
| 486 : super(map, key, delegate); | 462 : super(map, key, delegate); |
| 487 | 463 |
| 488 V operator [](int index) => elementAt(index); | 464 V operator [](int index) => elementAt(index); |
| 489 | 465 |
| 490 void operator []=(int index, V value) { | 466 void operator []=(int index, V value) { |
| 491 _syncDelegate(); | 467 _syncDelegate(); |
| 492 _delegate[index] = value; | 468 _delegate[index] = value; |
| 493 } | 469 } |
| 494 | 470 |
| 495 void add(V value) { | 471 void add(V value) { |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 657 _syncDelegate(); | 633 _syncDelegate(); |
| 658 _delegate.clear(); | 634 _delegate.clear(); |
| 659 _map.remove(_key); | 635 _map.remove(_key); |
| 660 } | 636 } |
| 661 | 637 |
| 662 bool containsAll(Iterable<Object> other) { | 638 bool containsAll(Iterable<Object> other) { |
| 663 _syncDelegate(); | 639 _syncDelegate(); |
| 664 return _delegate.containsAll(other); | 640 return _delegate.containsAll(other); |
| 665 } | 641 } |
| 666 | 642 |
| 667 Set<V> difference(Set<V> other) { | 643 Set<V> difference(Set<Object> other) { |
| 668 _syncDelegate(); | 644 _syncDelegate(); |
| 669 return _delegate.difference(other); | 645 return _delegate.difference(other); |
| 670 } | 646 } |
| 671 | 647 |
| 672 Set<V> intersection(Set<Object> other) { | 648 Set<V> intersection(Set<Object> other) { |
| 673 _syncDelegate(); | 649 _syncDelegate(); |
| 674 return _delegate.intersection(other); | 650 return _delegate.intersection(other); |
| 675 } | 651 } |
| 676 | 652 |
| 677 V lookup(Object object) { | 653 V lookup(Object object) { |
| (...skipping 30 matching lines...) Expand all Loading... |
| 708 _syncDelegate(); | 684 _syncDelegate(); |
| 709 _delegate.retainWhere(test); | 685 _delegate.retainWhere(test); |
| 710 if (_delegate.isEmpty) _map.remove(_key); | 686 if (_delegate.isEmpty) _map.remove(_key); |
| 711 } | 687 } |
| 712 | 688 |
| 713 Set<V> union(Set<V> other) { | 689 Set<V> union(Set<V> other) { |
| 714 _syncDelegate(); | 690 _syncDelegate(); |
| 715 return _delegate.union(other); | 691 return _delegate.union(other); |
| 716 } | 692 } |
| 717 } | 693 } |
| OLD | NEW |