blob: 4c5101eee6b912456c115620fd55469beff97c49 [file] [log] [blame]
// 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})";
}