OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 /** | 5 import "dart:collection"; |
6 * Delegating wrappers for [Iterable], [List], [Set], [Queue] and [Map]. | 6 import "dart:math" as math; |
7 * | |
8 * Also adds unmodifiable views for `Set` and `Map`, and a fixed length | |
9 * view for `List`. The unmodifiable list view from `dart:collection` is | |
10 * exported as well, just for completeness. | |
11 */ | |
12 library dart.pkg.collection.wrappers; | |
13 | 7 |
14 import "dart:collection"; | 8 import "unmodifiable_wrappers.dart"; |
15 import "dart:math" show Random; | |
16 | 9 |
17 import "src/unmodifiable_wrappers.dart"; | 10 /// A base class for delegating iterables. |
18 | 11 /// |
19 export "src/canonicalized_map.dart"; | 12 /// Subclasses can provide a [_base] that should be delegated to. Unlike |
20 export "src/unmodifiable_wrappers.dart"; | 13 /// [DelegatingIterable], this allows the base to be created on demand. |
21 | |
22 /** | |
23 * A base class for delegating iterables. | |
24 * | |
25 * Subclasses can provide a [_base] that should be delegated to. Unlike | |
26 * [DelegatingIterable], this allows the base to be created on demand. | |
27 */ | |
28 abstract class _DelegatingIterableBase<E> implements Iterable<E> { | 14 abstract class _DelegatingIterableBase<E> implements Iterable<E> { |
29 Iterable<E> get _base; | 15 Iterable<E> get _base; |
30 | 16 |
31 const _DelegatingIterableBase(); | 17 const _DelegatingIterableBase(); |
32 | 18 |
33 bool any(bool test(E element)) => _base.any(test); | 19 bool any(bool test(E element)) => _base.any(test); |
34 | 20 |
35 bool contains(Object element) => _base.contains(element); | 21 bool contains(Object element) => _base.contains(element); |
36 | 22 |
37 E elementAt(int index) => _base.elementAt(index); | 23 E elementAt(int index) => _base.elementAt(index); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
83 | 69 |
84 List<E> toList({bool growable: true}) => _base.toList(growable: growable); | 70 List<E> toList({bool growable: true}) => _base.toList(growable: growable); |
85 | 71 |
86 Set<E> toSet() => _base.toSet(); | 72 Set<E> toSet() => _base.toSet(); |
87 | 73 |
88 Iterable<E> where(bool test(E element)) => _base.where(test); | 74 Iterable<E> where(bool test(E element)) => _base.where(test); |
89 | 75 |
90 String toString() => _base.toString(); | 76 String toString() => _base.toString(); |
91 } | 77 } |
92 | 78 |
93 /** | 79 /// Creates an [Iterable] that delegates all operations to a base iterable. |
94 * Creates an [Iterable] that delegates all operations to a base iterable. | 80 /// |
95 * | 81 /// This class can be used hide non-`Iterable` methods of an iterable object, |
96 * This class can be used hide non-`Iterable` methods of an iterable object, | 82 /// or it can be extended to add extra functionality on top of an existing |
97 * or it can be extended to add extra functionality on top of an existing | 83 /// iterable object. |
98 * iterable object. | |
99 */ | |
100 class DelegatingIterable<E> extends _DelegatingIterableBase<E> { | 84 class DelegatingIterable<E> extends _DelegatingIterableBase<E> { |
101 final Iterable<E> _base; | 85 final Iterable<E> _base; |
102 | 86 |
103 /** | 87 /// Create a wrapper that forwards operations to [base]. |
104 * Create a wrapper that forwards operations to [base]. | |
105 */ | |
106 const DelegatingIterable(Iterable<E> base) : _base = base; | 88 const DelegatingIterable(Iterable<E> base) : _base = base; |
107 } | 89 } |
108 | 90 |
109 | 91 |
110 /** | 92 /// Creates a [List] that delegates all operations to a base list. |
111 * Creates a [List] that delegates all operations to a base list. | 93 /// |
112 * | 94 /// This class can be used hide non-`List` methods of a list object, |
113 * This class can be used hide non-`List` methods of a list object, | 95 /// or it can be extended to add extra functionality on top of an existing |
114 * or it can be extended to add extra functionality on top of an existing | 96 /// list object. |
115 * list object. | |
116 */ | |
117 class DelegatingList<E> extends DelegatingIterable<E> implements List<E> { | 97 class DelegatingList<E> extends DelegatingIterable<E> implements List<E> { |
118 const DelegatingList(List<E> base) : super(base); | 98 const DelegatingList(List<E> base) : super(base); |
119 | 99 |
120 List<E> get _listBase => _base; | 100 List<E> get _listBase => _base; |
121 | 101 |
122 E operator [](int index) => _listBase[index]; | 102 E operator [](int index) => _listBase[index]; |
123 | 103 |
124 void operator []=(int index, E value) { | 104 void operator []=(int index, E value) { |
125 _listBase[index] = value; | 105 _listBase[index] = value; |
126 } | 106 } |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
187 Iterable<E> get reversed => _listBase.reversed; | 167 Iterable<E> get reversed => _listBase.reversed; |
188 | 168 |
189 void setAll(int index, Iterable<E> iterable) { | 169 void setAll(int index, Iterable<E> iterable) { |
190 _listBase.setAll(index, iterable); | 170 _listBase.setAll(index, iterable); |
191 } | 171 } |
192 | 172 |
193 void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) { | 173 void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) { |
194 _listBase.setRange(start, end, iterable, skipCount); | 174 _listBase.setRange(start, end, iterable, skipCount); |
195 } | 175 } |
196 | 176 |
197 void shuffle([Random random]) { | 177 void shuffle([math.Random random]) { |
198 _listBase.shuffle(random); | 178 _listBase.shuffle(random); |
199 } | 179 } |
200 | 180 |
201 void sort([int compare(E a, E b)]) { | 181 void sort([int compare(E a, E b)]) { |
202 _listBase.sort(compare); | 182 _listBase.sort(compare); |
203 } | 183 } |
204 | 184 |
205 List<E> sublist(int start, [int end]) => _listBase.sublist(start, end); | 185 List<E> sublist(int start, [int end]) => _listBase.sublist(start, end); |
206 } | 186 } |
207 | 187 |
208 | 188 |
209 /** | 189 /// Creates a [Set] that delegates all operations to a base set. |
210 * Creates a [Set] that delegates all operations to a base set. | 190 /// |
211 * | 191 /// This class can be used hide non-`Set` methods of a set object, |
212 * This class can be used hide non-`Set` methods of a set object, | 192 /// or it can be extended to add extra functionality on top of an existing |
213 * or it can be extended to add extra functionality on top of an existing | 193 /// set object. |
214 * set object. | |
215 */ | |
216 class DelegatingSet<E> extends DelegatingIterable<E> implements Set<E> { | 194 class DelegatingSet<E> extends DelegatingIterable<E> implements Set<E> { |
217 const DelegatingSet(Set<E> base) : super(base); | 195 const DelegatingSet(Set<E> base) : super(base); |
218 | 196 |
219 Set<E> get _setBase => _base; | 197 Set<E> get _setBase => _base; |
220 | 198 |
221 bool add(E value) => _setBase.add(value); | 199 bool add(E value) => _setBase.add(value); |
222 | 200 |
223 void addAll(Iterable<E> elements) { | 201 void addAll(Iterable<E> elements) { |
224 _setBase.addAll(elements); | 202 _setBase.addAll(elements); |
225 } | 203 } |
(...skipping 26 matching lines...) Expand all Loading... |
252 | 230 |
253 void retainWhere(bool test(E element)) { | 231 void retainWhere(bool test(E element)) { |
254 _setBase.retainWhere(test); | 232 _setBase.retainWhere(test); |
255 } | 233 } |
256 | 234 |
257 Set<E> union(Set<E> other) => _setBase.union(other); | 235 Set<E> union(Set<E> other) => _setBase.union(other); |
258 | 236 |
259 Set<E> toSet() => new DelegatingSet<E>(_setBase.toSet()); | 237 Set<E> toSet() => new DelegatingSet<E>(_setBase.toSet()); |
260 } | 238 } |
261 | 239 |
262 /** | 240 /// Creates a [Queue] that delegates all operations to a base queue. |
263 * Creates a [Queue] that delegates all operations to a base queue. | 241 /// |
264 * | 242 /// This class can be used hide non-`Queue` methods of a queue object, |
265 * This class can be used hide non-`Queue` methods of a queue object, | 243 /// or it can be extended to add extra functionality on top of an existing |
266 * or it can be extended to add extra functionality on top of an existing | 244 /// queue object. |
267 * queue object. | |
268 */ | |
269 class DelegatingQueue<E> extends DelegatingIterable<E> implements Queue<E> { | 245 class DelegatingQueue<E> extends DelegatingIterable<E> implements Queue<E> { |
270 const DelegatingQueue(Queue<E> queue) : super(queue); | 246 const DelegatingQueue(Queue<E> queue) : super(queue); |
271 | 247 |
272 Queue<E> get _baseQueue => _base; | 248 Queue<E> get _baseQueue => _base; |
273 | 249 |
274 void add(E value) { | 250 void add(E value) { |
275 _baseQueue.add(value); | 251 _baseQueue.add(value); |
276 } | 252 } |
277 | 253 |
278 void addAll(Iterable<E> iterable) { | 254 void addAll(Iterable<E> iterable) { |
(...skipping 16 matching lines...) Expand all Loading... |
295 | 271 |
296 void removeWhere(bool test(E element)) { _baseQueue.removeWhere(test); } | 272 void removeWhere(bool test(E element)) { _baseQueue.removeWhere(test); } |
297 | 273 |
298 void retainWhere(bool test(E element)) { _baseQueue.retainWhere(test); } | 274 void retainWhere(bool test(E element)) { _baseQueue.retainWhere(test); } |
299 | 275 |
300 E removeFirst() => _baseQueue.removeFirst(); | 276 E removeFirst() => _baseQueue.removeFirst(); |
301 | 277 |
302 E removeLast() => _baseQueue.removeLast(); | 278 E removeLast() => _baseQueue.removeLast(); |
303 } | 279 } |
304 | 280 |
305 /** | 281 /// Creates a [Map] that delegates all operations to a base map. |
306 * Creates a [Map] that delegates all operations to a base map. | 282 /// |
307 * | 283 /// This class can be used hide non-`Map` methods of an object that extends |
308 * This class can be used hide non-`Map` methods of an object that extends | 284 /// `Map`, or it can be extended to add extra functionality on top of an |
309 * `Map`, or it can be extended to add extra functionality on top of an existing | 285 /// existing map object. |
310 * map object. | |
311 */ | |
312 class DelegatingMap<K, V> implements Map<K, V> { | 286 class DelegatingMap<K, V> implements Map<K, V> { |
313 final Map<K, V> _base; | 287 final Map<K, V> _base; |
314 | 288 |
315 const DelegatingMap(Map<K, V> base) : _base = base; | 289 const DelegatingMap(Map<K, V> base) : _base = base; |
316 | 290 |
317 V operator [](Object key) => _base[key]; | 291 V operator [](Object key) => _base[key]; |
318 | 292 |
319 void operator []=(K key, V value) { | 293 void operator []=(K key, V value) { |
320 _base[key] = value; | 294 _base[key] = value; |
321 } | 295 } |
(...skipping 24 matching lines...) Expand all Loading... |
346 | 320 |
347 V putIfAbsent(K key, V ifAbsent()) => _base.putIfAbsent(key, ifAbsent); | 321 V putIfAbsent(K key, V ifAbsent()) => _base.putIfAbsent(key, ifAbsent); |
348 | 322 |
349 V remove(Object key) => _base.remove(key); | 323 V remove(Object key) => _base.remove(key); |
350 | 324 |
351 Iterable<V> get values => _base.values; | 325 Iterable<V> get values => _base.values; |
352 | 326 |
353 String toString() => _base.toString(); | 327 String toString() => _base.toString(); |
354 } | 328 } |
355 | 329 |
356 /** | 330 /// An unmodifiable [Set] view of the keys of a [Map]. |
357 * An unmodifiable [Set] view of the keys of a [Map]. | 331 /// |
358 * | 332 /// The set delegates all operations to the underlying map. |
359 * The set delegates all operations to the underlying map. | 333 /// |
360 * | 334 /// A `Map` can only contain each key once, so its keys can always |
361 * A `Map` can only contain each key once, so its keys can always | 335 /// be viewed as a `Set` without any loss, even if the [Map.keys] |
362 * be viewed as a `Set` without any loss, even if the [Map.keys] | 336 /// getter only shows an [Iterable] view of the keys. |
363 * getter only shows an [Iterable] view of the keys. | 337 /// |
364 * | 338 /// Note that [lookup] is not supported for this set. |
365 * Note that [lookup] is not supported for this set. | |
366 */ | |
367 class MapKeySet<E> extends _DelegatingIterableBase<E> | 339 class MapKeySet<E> extends _DelegatingIterableBase<E> |
368 with UnmodifiableSetMixin<E> { | 340 with UnmodifiableSetMixin<E> { |
369 final Map<E, dynamic> _baseMap; | 341 final Map<E, dynamic> _baseMap; |
370 | 342 |
371 MapKeySet(Map<E, dynamic> base) : _baseMap = base; | 343 MapKeySet(Map<E, dynamic> base) : _baseMap = base; |
372 | 344 |
373 Iterable<E> get _base => _baseMap.keys; | 345 Iterable<E> get _base => _baseMap.keys; |
374 | 346 |
375 bool contains(Object element) => _baseMap.containsKey(element); | 347 bool contains(Object element) => _baseMap.containsKey(element); |
376 | 348 |
377 bool get isEmpty => _baseMap.isEmpty; | 349 bool get isEmpty => _baseMap.isEmpty; |
378 | 350 |
379 bool get isNotEmpty => _baseMap.isNotEmpty; | 351 bool get isNotEmpty => _baseMap.isNotEmpty; |
380 | 352 |
381 int get length => _baseMap.length; | 353 int get length => _baseMap.length; |
382 | 354 |
383 String toString() => "{${_base.join(', ')}}"; | 355 String toString() => "{${_base.join(', ')}}"; |
384 | 356 |
385 bool containsAll(Iterable<Object> other) => other.every(contains); | 357 bool containsAll(Iterable<Object> other) => other.every(contains); |
386 | 358 |
387 /** | 359 /// Returns a new set with the the elements of [this] that are not in [other]. |
388 * Returns a new set with the the elements of [this] that are not in [other]. | 360 /// |
389 * | 361 /// That is, the returned set contains all the elements of this [Set] that are |
390 * That is, the returned set contains all the elements of this [Set] that are | 362 /// not elements of [other] according to `other.contains`. |
391 * not elements of [other] according to `other.contains`. | 363 /// |
392 * | 364 /// Note that the returned set will use the default equality operation, which |
393 * Note that the returned set will use the default equality operation, which | 365 /// may be different than the equality operation [this] uses. |
394 * may be different than the equality operation [this] uses. | |
395 */ | |
396 Set<E> difference(Set<E> other) => | 366 Set<E> difference(Set<E> other) => |
397 where((element) => !other.contains(element)).toSet(); | 367 where((element) => !other.contains(element)).toSet(); |
398 | 368 |
399 /** | 369 /// Returns a new set which is the intersection between [this] and [other]. |
400 * Returns a new set which is the intersection between [this] and [other]. | 370 /// |
401 * | 371 /// That is, the returned set contains all the elements of this [Set] that are |
402 * That is, the returned set contains all the elements of this [Set] that are | 372 /// also elements of [other] according to `other.contains`. |
403 * also elements of [other] according to `other.contains`. | 373 /// |
404 * | 374 /// Note that the returned set will use the default equality operation, which |
405 * Note that the returned set will use the default equality operation, which | 375 /// may be different than the equality operation [this] uses. |
406 * may be different than the equality operation [this] uses. | |
407 */ | |
408 Set<E> intersection(Set<Object> other) => where(other.contains).toSet(); | 376 Set<E> intersection(Set<Object> other) => where(other.contains).toSet(); |
409 | 377 |
410 /** | 378 /// Throws an [UnsupportedError] since there's no corresponding method for |
411 * Throws an [UnsupportedError] since there's no corresponding method for | 379 /// [Map]s. |
412 * [Map]s. | |
413 */ | |
414 E lookup(E element) => throw new UnsupportedError( | 380 E lookup(E element) => throw new UnsupportedError( |
415 "MapKeySet doesn't support lookup()."); | 381 "MapKeySet doesn't support lookup()."); |
416 | 382 |
417 /** | 383 /// Returns a new set which contains all the elements of [this] and [other]. |
418 * Returns a new set which contains all the elements of [this] and [other]. | 384 /// |
419 * | 385 /// That is, the returned set contains all the elements of this [Set] and all |
420 * That is, the returned set contains all the elements of this [Set] and all | 386 /// the elements of [other]. |
421 * the elements of [other]. | 387 /// |
422 * | 388 /// Note that the returned set will use the default equality operation, which |
423 * Note that the returned set will use the default equality operation, which | 389 /// may be different than the equality operation [this] uses. |
424 * may be different than the equality operation [this] uses. | |
425 */ | |
426 Set<E> union(Set<E> other) => toSet()..addAll(other); | 390 Set<E> union(Set<E> other) => toSet()..addAll(other); |
427 } | 391 } |
428 | 392 |
429 /** | 393 /// Creates a modifiable [Set] view of the values of a [Map]. |
430 * Creates a modifiable [Set] view of the values of a [Map]. | 394 /// |
431 * | 395 /// The `Set` view assumes that the keys of the `Map` can be uniquely determined |
432 * The `Set` view assumes that the keys of the `Map` can be uniquely determined | 396 /// from the values. The `keyForValue` function passed to the constructor finds |
433 * from the values. The `keyForValue` function passed to the constructor finds | 397 /// the key for a single value. The `keyForValue` function should be consistent |
434 * the key for a single value. The `keyForValue` function should be consistent | 398 /// with equality. If `value1 == value2` then `keyForValue(value1)` and |
435 * with equality. If `value1 == value2` then `keyForValue(value1)` and | 399 /// `keyForValue(value2)` should be considered equal keys by the underlying map, |
436 * `keyForValue(value2)` should be considered equal keys by the underlying map, | 400 /// and vice versa. |
437 * and vice versa. | 401 /// |
438 * | 402 /// Modifying the set will modify the underlying map based on the key returned |
439 * Modifying the set will modify the underlying map based on the key returned by | 403 /// by `keyForValue`. |
440 * `keyForValue`. | 404 /// |
441 * | 405 /// If the `Map` contents are not compatible with the `keyForValue` function, |
442 * If the `Map` contents are not compatible with the `keyForValue` function, the | 406 /// the set will not work consistently, and may give meaningless responses or do |
443 * set will not work consistently, and may give meaningless responses or do | 407 /// inconsistent updates. |
444 * inconsistent updates. | 408 /// |
445 * | 409 /// This set can, for example, be used on a map from database record IDs to the |
446 * This set can, for example, be used on a map from database record IDs to the | 410 /// records. It exposes the records as a set, and allows for writing both |
447 * records. It exposes the records as a set, and allows for writing both | 411 /// `recordSet.add(databaseRecord)` and `recordMap[id]`. |
448 * `recordSet.add(databaseRecord)` and `recordMap[id]`. | 412 /// |
449 * | 413 /// Effectively, the map will act as a kind of index for the set. |
450 * Effectively, the map will act as a kind of index for the set. | |
451 */ | |
452 class MapValueSet<K, V> extends _DelegatingIterableBase<V> implements Set<V> { | 414 class MapValueSet<K, V> extends _DelegatingIterableBase<V> implements Set<V> { |
453 final Map<K, V> _baseMap; | 415 final Map<K, V> _baseMap; |
454 final Function _keyForValue; | 416 final Function _keyForValue; |
455 | 417 |
456 /** | 418 /// Creates a new [MapValueSet] based on [base]. |
457 * Creates a new [MapValueSet] based on [base]. | 419 /// |
458 * | 420 /// [keyForValue] returns the key in the map that should be associated with |
459 * [keyForValue] returns the key in the map that should be associated with the | 421 /// the given value. The set's notion of equality is identical to the equality |
460 * given value. The set's notion of equality is identical to the equality of | 422 /// of the return values of [keyForValue]. |
461 * the return values of [keyForValue]. | |
462 */ | |
463 MapValueSet(Map<K, V> base, K keyForValue(V value)) | 423 MapValueSet(Map<K, V> base, K keyForValue(V value)) |
464 : _baseMap = base, | 424 : _baseMap = base, |
465 _keyForValue = keyForValue; | 425 _keyForValue = keyForValue; |
466 | 426 |
467 Iterable<V> get _base => _baseMap.values; | 427 Iterable<V> get _base => _baseMap.values; |
468 | 428 |
469 bool contains(Object element) { | 429 bool contains(Object element) { |
470 if (element != null && element is! V) return false; | 430 if (element != null && element is! V) return false; |
471 return _baseMap.containsKey(_keyForValue(element)); | 431 return _baseMap.containsKey(_keyForValue(element)); |
472 } | 432 } |
(...skipping 15 matching lines...) Expand all Loading... |
488 }); | 448 }); |
489 return result; | 449 return result; |
490 } | 450 } |
491 | 451 |
492 void addAll(Iterable<V> elements) => elements.forEach(add); | 452 void addAll(Iterable<V> elements) => elements.forEach(add); |
493 | 453 |
494 void clear() => _baseMap.clear(); | 454 void clear() => _baseMap.clear(); |
495 | 455 |
496 bool containsAll(Iterable<Object> other) => other.every(contains); | 456 bool containsAll(Iterable<Object> other) => other.every(contains); |
497 | 457 |
498 /** | 458 /// Returns a new set with the the elements of [this] that are not in [other]. |
499 * Returns a new set with the the elements of [this] that are not in [other]. | 459 /// |
500 * | 460 /// That is, the returned set contains all the elements of this [Set] that are |
501 * That is, the returned set contains all the elements of this [Set] that are | 461 /// not elements of [other] according to `other.contains`. |
502 * not elements of [other] according to `other.contains`. | 462 /// |
503 * | 463 /// Note that the returned set will use the default equality operation, which |
504 * Note that the returned set will use the default equality operation, which | 464 /// may be different than the equality operation [this] uses. |
505 * may be different than the equality operation [this] uses. | |
506 */ | |
507 Set<V> difference(Set<V> other) => | 465 Set<V> difference(Set<V> other) => |
508 where((element) => !other.contains(element)).toSet(); | 466 where((element) => !other.contains(element)).toSet(); |
509 | 467 |
510 /** | 468 /// Returns a new set which is the intersection between [this] and [other]. |
511 * Returns a new set which is the intersection between [this] and [other]. | 469 /// |
512 * | 470 /// That is, the returned set contains all the elements of this [Set] that are |
513 * That is, the returned set contains all the elements of this [Set] that are | 471 /// also elements of [other] according to `other.contains`. |
514 * also elements of [other] according to `other.contains`. | 472 /// |
515 * | 473 /// Note that the returned set will use the default equality operation, which |
516 * Note that the returned set will use the default equality operation, which | 474 /// may be different than the equality operation [this] uses. |
517 * may be different than the equality operation [this] uses. | |
518 */ | |
519 Set<V> intersection(Set<Object> other) => where(other.contains).toSet(); | 475 Set<V> intersection(Set<Object> other) => where(other.contains).toSet(); |
520 | 476 |
521 V lookup(Object element) => _baseMap[_keyForValue(element)]; | 477 V lookup(Object element) => _baseMap[_keyForValue(element)]; |
522 | 478 |
523 bool remove(Object value) { | 479 bool remove(Object value) { |
524 if (value != null && value is! V) return false; | 480 if (value != null && value is! V) return false; |
525 var key = _keyForValue(value); | 481 var key = _keyForValue(value); |
526 if (!_baseMap.containsKey(key)) return false; | 482 if (!_baseMap.containsKey(key)) return false; |
527 _baseMap.remove(key); | 483 _baseMap.remove(key); |
528 return true; | 484 return true; |
(...skipping 21 matching lines...) Expand all Loading... |
550 var keysToRemove = []; | 506 var keysToRemove = []; |
551 _baseMap.forEach((k, v) { | 507 _baseMap.forEach((k, v) { |
552 if (!valuesToRetain.contains(v)) keysToRemove.add(k); | 508 if (!valuesToRetain.contains(v)) keysToRemove.add(k); |
553 }); | 509 }); |
554 keysToRemove.forEach(_baseMap.remove); | 510 keysToRemove.forEach(_baseMap.remove); |
555 } | 511 } |
556 | 512 |
557 void retainWhere(bool test(V element)) => | 513 void retainWhere(bool test(V element)) => |
558 removeWhere((element) => !test(element)); | 514 removeWhere((element) => !test(element)); |
559 | 515 |
560 /** | 516 /// Returns a new set which contains all the elements of [this] and [other]. |
561 * Returns a new set which contains all the elements of [this] and [other]. | 517 /// |
562 * | 518 /// That is, the returned set contains all the elements of this [Set] and all |
563 * That is, the returned set contains all the elements of this [Set] and all | 519 /// the elements of [other]. |
564 * the elements of [other]. | 520 /// |
565 * | 521 /// Note that the returned set will use the default equality operation, which |
566 * Note that the returned set will use the default equality operation, which | 522 /// may be different than the equality operation [this] uses. |
567 * may be different than the equality operation [this] uses. | |
568 */ | |
569 Set<V> union(Set<V> other) => toSet()..addAll(other); | 523 Set<V> union(Set<V> other) => toSet()..addAll(other); |
570 } | 524 } |
OLD | NEW |