| // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| import 'dart:collection'; |
| |
| /// The expensive set is a data structure useful for tracking down |
| /// excessive memory usage due to large sets. It acts as an ordinary |
| /// hash set, but it uses 10 times more memory (by default). |
| class ExpensiveSet<E> extends SetBase<E> { |
| final List _sets; |
| |
| ExpensiveSet([int copies = 10]) : _sets = new List(copies) { |
| assert(copies > 0); |
| for (int i = 0; i < _sets.length; i++) { |
| _sets[i] = new Set<E>(); |
| } |
| } |
| |
| @override |
| int get length => _sets[0].length; |
| @override |
| bool get isEmpty => _sets[0].isEmpty; |
| @override |
| bool get isNotEmpty => _sets[0].isNotEmpty; |
| |
| @override |
| Iterator<E> get iterator => _sets[0].iterator; |
| |
| @override |
| bool contains(Object object) => _sets[0].contains(object); |
| @override |
| E lookup(Object object) => _sets[0].lookup(object); |
| |
| @override |
| void forEach(void action(E element)) { |
| _sets[0].forEach(action); |
| } |
| |
| @override |
| bool add(E element) { |
| bool result = _sets[0].add(element); |
| for (int i = 1; i < _sets.length; i++) { |
| _sets[i].add(element); |
| } |
| return result; |
| } |
| |
| @override |
| void addAll(Iterable<E> objects) { |
| for (E each in objects) { |
| add(each); |
| } |
| } |
| |
| @override |
| bool remove(Object object) { |
| bool result = _sets[0].remove(object); |
| for (int i = 1; i < _sets.length; i++) { |
| _sets[i].remove(object); |
| } |
| return result; |
| } |
| |
| @override |
| void clear() { |
| for (int i = 0; i < _sets.length; i++) { |
| _sets[i].clear(); |
| } |
| } |
| |
| @override |
| void removeAll(Iterable<Object> objectsToRemove) { |
| for (var each in objectsToRemove) { |
| remove(each); |
| } |
| } |
| |
| @override |
| void removeWhere(bool test(E element)) { |
| removeAll(this.toList().where((e) => test(e))); |
| } |
| |
| @override |
| void retainWhere(bool test(E element)) { |
| removeAll(toList().where((e) => !test(e))); |
| } |
| |
| @override |
| bool containsAll(Iterable<Object> other) { |
| for (Object object in other) { |
| if (!this.contains(object)) return false; |
| } |
| return true; |
| } |
| |
| Set _newSet() => new ExpensiveSet(_sets.length); |
| |
| @override |
| Set<E> intersection(Set<Object> other) { |
| Set<E> result = _newSet(); |
| if (other.length < this.length) { |
| for (var element in other) { |
| if (this.contains(element)) result.add(element); |
| } |
| } else { |
| for (E element in this) { |
| if (other.contains(element)) result.add(element); |
| } |
| } |
| return result; |
| } |
| |
| @override |
| Set<E> union(Set<E> other) { |
| return _newSet()..addAll(this)..addAll(other); |
| } |
| |
| @override |
| Set<E> difference(Set<Object> other) { |
| Set<E> result = _newSet(); |
| for (E element in this) { |
| if (!other.contains(element)) result.add(element); |
| } |
| return result; |
| } |
| |
| @override |
| void retainAll(Iterable objectsToRetain) { |
| Set retainSet; |
| if (objectsToRetain is Set) { |
| retainSet = objectsToRetain; |
| } else { |
| retainSet = objectsToRetain.toSet(); |
| } |
| retainWhere(retainSet.contains); |
| } |
| |
| @override |
| Set<E> toSet() { |
| var result = new ExpensiveSet<E>(_sets.length); |
| for (int i = 0; i < _sets.length; i++) { |
| result._sets[i] = _sets[i].toSet(); |
| } |
| return result; |
| } |
| |
| @override |
| String toString() => "expensive(${_sets[0]}x${_sets.length})"; |
| } |