diff --git a/README.md b/README.md index 034766b..1af3e7a 100644 --- a/README.md +++ b/README.md @@ -67,17 +67,15 @@ Note that you could instead just create a `MappingOrderedSet` instead: // ... ``` -## Mapping vs Comparing vs Queryable +## Mapping vs Comparing -There are three main implementations of the `OrderedSet` interface: +There are two main implementations of the `OrderedSet` interface: * `ComparingOrderedSet`: the simplest implementation, takes in a `Comparator` and does not cache priorities. It uses Dart's `SplayTreeSet` as a backing implementation. * `MappingOrderedSet`: a slightly more advanced implementation that takes in a mapper function (maps elements to their priorities) and caches them. It uses Dart's `SplayTreeMap` as a backing implementation. -* `QueryableOrderedSet`: a simple wrapper over either `OrderedSet` that allows for O(1) type - queries; if you find yourself doing `.whereType()` a lot, you should consider using this. In order to create an `OrderedSet`, however, you can just use the static methods on the interface itself: @@ -90,10 +88,19 @@ itself: a `MappingOrderedSet` with identity mapping. * `OrderedSet.simple()`: if `E extends Comparable`, this is an even simpler way of creating a `MappingOrderedSet` with identity mapping. -* `OrderedSet.queryable(orderedSet)`: wraps the given `OrderedSet` into a `QueryableOrderedSet`. + +## Querying + +You can [register] a set of queries, i.e., predefined sub-types, whose results, i.e., subsets of +this set, are then cached. Since the queries have to be type checks, and types are runtime +constants, this can be vastly optimized. + +You can then filter by type by using the [query] method (or using [whereType]; which is overridden). + +Note that you can change [strictMode] to allow for querying for unregistered types; if you do so, +the registration cost is payed on the first query. ## Contributing All contributions are very welcome! Please feel free to create Issues, help us with PR's or comment your suggestions, feature requests, bugs, et cetera. Give us a star if you liked it! - diff --git a/benchmark/main.dart b/benchmark/main.dart index 4c86258..88f4d22 100644 --- a/benchmark/main.dart +++ b/benchmark/main.dart @@ -8,7 +8,7 @@ import 'types.dart'; void main() { OrderedSet comparing(Mapper mapper) { - return OrderedSet.comparing(Comparing.on(mapper)); + return OrderedSet.comparing(compare: Comparing.on(mapper)); } OrderedSet priority(Mapper mapper) { diff --git a/example/ordered_set_example.dart b/example/ordered_set_example.dart index 429c794..30f605d 100644 --- a/example/ordered_set_example.dart +++ b/example/ordered_set_example.dart @@ -9,7 +9,7 @@ void main() { items.add(1); print(items.toList()); // [1, 2] - final a = OrderedSet.comparing((a, b) => a.age - b.age); + final a = OrderedSet.comparing(compare: (a, b) => a.age - b.age); a.add(Person(12, 'Klaus')); a.add(Person(1, 'Sunny')); a.add(Person(14, 'Violet')); @@ -25,7 +25,7 @@ void main() { // use Comparing for simpler creation: // sort by age desc and then name asc final b = OrderedSet.comparing( - Comparing.join([(p) => -p.age, (p) => p.name]), + compare: Comparing.join([(p) => -p.age, (p) => p.name]), ); b.addAll(a.toList()); print(b.toList().map((e) => e.name)); diff --git a/lib/comparing_ordered_set.dart b/lib/comparing_ordered_set.dart index da1b6e1..809be7d 100644 --- a/lib/comparing_ordered_set.dart +++ b/lib/comparing_ordered_set.dart @@ -3,6 +3,7 @@ import 'dart:collection'; import 'package:ordered_set/mapping_ordered_set.dart'; import 'package:ordered_set/ordered_set.dart'; import 'package:ordered_set/ordered_set_iterator.dart'; +import 'package:ordered_set/queryable_ordered_set_impl.dart'; /// A simple implementation of [OrderedSet] that uses a [SplayTreeSet] as the /// backing store. @@ -10,16 +11,23 @@ import 'package:ordered_set/ordered_set_iterator.dart'; /// This does not store the elements priorities, so it is susceptible to race /// conditions if priorities are changed while iterating. /// For a safer implementation, use [MappingOrderedSet]. -class ComparingOrderedSet extends OrderedSet { +class ComparingOrderedSet extends OrderedSet + with QueryableOrderedSetImpl { // If the default implementation of `Set` changes from `LinkedHashSet` to // something else that isn't ordered we'll have to change this to explicitly // be `LinkedHashSet` (or some other data structure that preserves order). - late SplayTreeSet> _backingSet; - late int _length; + late final SplayTreeSet> _backingSet = SplayTreeSet>( + _outerComparator, + ); + final int Function(E e1, E e2) _comparator; + int _length = 0; bool _validReverseCache = true; Iterable _reverseCache = const Iterable.empty(); + @override + final bool strictMode; + // Copied from SplayTreeSet, but those are private there static int _dynamicCompare(dynamic a, dynamic b) => Comparable.compare( a as Comparable, @@ -37,22 +45,10 @@ class ComparingOrderedSet extends OrderedSet { /// /// If the [compare] function is omitted, it defaults to [Comparable.compare], /// and the elements must be comparable. - ComparingOrderedSet([int Function(E e1, E e2)? compare]) { - final comparator = compare ?? _defaultCompare(); - _backingSet = SplayTreeSet>((Set l1, Set l2) { - if (l1.isEmpty) { - if (l2.isEmpty) { - return 0; - } - return -1; - } - if (l2.isEmpty) { - return 1; - } - return comparator(l1.first, l2.first); - }); - _length = 0; - } + ComparingOrderedSet({ + int Function(E e1, E e2)? compare, + this.strictMode = true, + }) : _comparator = compare ?? _defaultCompare(); @override int get length => _length; @@ -81,6 +77,7 @@ class ComparingOrderedSet extends OrderedSet { if (added) { _length++; _validReverseCache = false; + onAdd(e); } return added; } @@ -122,6 +119,7 @@ class ComparingOrderedSet extends OrderedSet { // If the removal resulted in an empty bucket, remove the bucket as well. _backingSet.remove({}); _validReverseCache = false; + onRemove(e); } return result; } @@ -131,5 +129,19 @@ class ComparingOrderedSet extends OrderedSet { _validReverseCache = false; _backingSet.clear(); _length = 0; + onClear(); + } + + int _outerComparator(Set l1, Set l2) { + if (l1.isEmpty) { + if (l2.isEmpty) { + return 0; + } + return -1; + } + if (l2.isEmpty) { + return 1; + } + return _comparator(l1.first, l2.first); } } diff --git a/lib/mapping_ordered_set.dart b/lib/mapping_ordered_set.dart index dabd1e7..59441af 100644 --- a/lib/mapping_ordered_set.dart +++ b/lib/mapping_ordered_set.dart @@ -3,6 +3,7 @@ import 'dart:collection'; import 'package:ordered_set/comparing_ordered_set.dart'; import 'package:ordered_set/ordered_set.dart'; import 'package:ordered_set/ordered_set_iterator.dart'; +import 'package:ordered_set/queryable_ordered_set_impl.dart'; /// A simple implementation of [OrderedSet] that uses a [SplayTreeMap] as the /// backing store. @@ -10,20 +11,22 @@ import 'package:ordered_set/ordered_set_iterator.dart'; /// This allows it to keep a cache of elements priorities, so they can be used /// changed without rebalancing. /// For an alternative implementation, use [ComparingOrderedSet]. -class MappingOrderedSet, E> extends OrderedSet { +class MappingOrderedSet, E> extends OrderedSet + with QueryableOrderedSetImpl { final K Function(E a) _mappingFunction; - late SplayTreeMap> _backingSet; - late int _length; + final SplayTreeMap> _backingSet; + int _length = 0; bool _validReverseCache = true; Iterable _reverseCache = const Iterable.empty(); - MappingOrderedSet(this._mappingFunction) { - _backingSet = SplayTreeMap((K k1, K k2) { - return k1.compareTo(k2); - }); - _length = 0; - } + @override + final bool strictMode; + + MappingOrderedSet( + this._mappingFunction, { + this.strictMode = true, + }) : _backingSet = SplayTreeMap((K k1, K k2) => k1.compareTo(k2)); @override int get length => _length; @@ -49,6 +52,7 @@ class MappingOrderedSet, E> extends OrderedSet { if (added) { _length++; _validReverseCache = false; + onAdd(e); } return added; } @@ -94,6 +98,7 @@ class MappingOrderedSet, E> extends OrderedSet { _backingSet.remove(key); } _validReverseCache = false; + onRemove(e); } return result; } @@ -103,5 +108,6 @@ class MappingOrderedSet, E> extends OrderedSet { _validReverseCache = false; _backingSet.clear(); _length = 0; + onClear(); } } diff --git a/lib/ordered_set.dart b/lib/ordered_set.dart index fd89456..44401f6 100644 --- a/lib/ordered_set.dart +++ b/lib/ordered_set.dart @@ -2,7 +2,7 @@ import 'dart:collection'; import 'package:ordered_set/comparing_ordered_set.dart'; import 'package:ordered_set/mapping_ordered_set.dart'; -import 'package:ordered_set/queryable_ordered_set.dart'; +import 'package:ordered_set/read_only_ordered_set.dart'; /// A simple interface of an ordered set for Dart. /// @@ -10,10 +10,7 @@ import 'package:ordered_set/queryable_ordered_set.dart'; /// [SplayTreeSet], it allows for several different elements with the same /// priority to be added. It also implements [Iterable], so you can iterate it /// in O(n). -abstract class OrderedSet extends IterableMixin { - /// The tree's elements in reversed order; should be cached when possible. - Iterable reversed(); - +abstract class OrderedSet extends ReadOnlyOrderedSet { /// Adds the element [e] to this, and returns whether the element was /// added or not. If the element already exists in the collection, it isn't /// added. @@ -67,12 +64,22 @@ abstract class OrderedSet extends IterableMixin { /// Remove all elements that match the [test] condition; returns the removed /// elements. Iterable removeWhere(bool Function(E element) test) { - return where(test).toList(growable: false)..forEach(remove); + final elements = where(test).toList(growable: false); + for (final element in elements) { + remove(element); + } + return elements; } /// Remove all [elements] and returns the removed elements. Iterable removeAll(Iterable elements) { - return elements.where(remove).toList(growable: false); + final removed = []; + for (final element in elements) { + if (remove(element)) { + removed.add(element); + } + } + return removed; } /// Removes the element at [index]. @@ -86,18 +93,20 @@ abstract class OrderedSet extends IterableMixin { /// /// This implementation will not store component priorities, so it is /// susceptible to race conditions if priorities are changed while iterating. - static ComparingOrderedSet comparing([ + static ComparingOrderedSet comparing({ int Function(E a, E b)? compare, - ]) { - return ComparingOrderedSet(compare); + bool strictMode = true, + }) { + return ComparingOrderedSet(compare: compare, strictMode: strictMode); } /// Creates an instance of [OrderedSet] using the [MappingOrderedSet] /// implementation and the provided [mappingFunction]. static MappingOrderedSet mapping, E>( - K Function(E a) mappingFunction, - ) { - return MappingOrderedSet(mappingFunction); + K Function(E a) mappingFunction, { + bool strictMode = true, + }) { + return MappingOrderedSet(mappingFunction, strictMode: strictMode); } /// Creates an instance of [OrderedSet] for items that are already @@ -105,24 +114,19 @@ abstract class OrderedSet extends IterableMixin { /// Use this for classes that implement [Comparable] of a different class. /// Equivalent to `mapping((a) => a)`. static MappingOrderedSet - comparable, E extends K>() { - return mapping((a) => a); + comparable, E extends K>({ + bool strictMode = true, + }) { + return mapping((a) => a, strictMode: strictMode); } /// Creates an instance of [OrderedSet] for items that are already /// [Comparable] of themselves, using the [MappingOrderedSet] implementation. /// Use this for classes that implement [Comparable] of themselves. /// Equivalent to `mapping((a) => a)`. - static MappingOrderedSet simple>() { - return comparable(); - } - - /// Creates an instance of [OrderedSet] using the [QueryableOrderedSet] - /// by wrapping the provided [backingSet]. - static QueryableOrderedSet queryable( - OrderedSet backingSet, { + static MappingOrderedSet simple>({ bool strictMode = true, }) { - return QueryableOrderedSet(backingSet, strictMode: strictMode); + return comparable(strictMode: strictMode); } } diff --git a/lib/queryable_ordered_set.dart b/lib/queryable_ordered_set.dart deleted file mode 100644 index 1bf5a72..0000000 --- a/lib/queryable_ordered_set.dart +++ /dev/null @@ -1,153 +0,0 @@ -import 'package:ordered_set/ordered_set.dart'; - -/// This is an implementation of [OrderedSet] that allows you to more -/// efficiently [query] the list. -/// -/// You can [register] a set of queries, i.e., predefined sub-types, whose -/// results, i.e., subsets of this set, are then cached. Since the queries -/// have to be type checks, and types are runtime constants, this can be -/// vastly optimized. -/// -/// If you find yourself doing a lot of: -/// -/// ```dart -/// orderedSet.whereType() -/// ``` -/// -/// On your code, and are concerned you are iterating a very long O(n) list to -/// find a handful of elements, specially if this is done every tick, you -/// can use this class, that pays a small O(number of registers) cost on [add], -/// but lets you find (specific) subsets at O(0). -/// -/// Note that you can change [strictMode] to allow for querying for unregistered -/// types; if you do so, the registration cost is payed on the first query. -class QueryableOrderedSet extends OrderedSet { - /// Controls whether running an unregistered query throws an error or - /// performs just-in-time filtering. - final bool strictMode; - final Map> _cache = {}; - final OrderedSet _backingSet; - - QueryableOrderedSet( - this._backingSet, { - this.strictMode = true, - }); - - /// Adds a new cache for a subtype [C] of [E], allowing you to call [query]. - /// If the cache already exists this operation is a no-op. - /// - /// If the set is not empty, the current elements will be re-sorted. - /// - /// It is recommended to [register] all desired types at the beginning of - /// your application to avoid recomputing the existing elements upon - /// registration. - void register() { - if (isRegistered()) { - return; - } - _cache[C] = _CacheEntry( - data: _filter(), - ); - } - - /// Allow you to find a subset of this set with all the elements `e` for - /// which the condition `e is C` is true. This is equivalent to - /// - /// ```dart - /// orderedSet.whereType() - /// ``` - /// - /// except that it is O(0). - /// - /// Note: you *must* call [register] for every type [C] you desire to use - /// before calling this, or set [strictMode] to false. - Iterable query() { - final result = _cache[C]; - if (result == null) { - if (strictMode) { - throw 'Cannot query unregistered query $C'; - } else { - register(); - return query(); - } - } - // We are returning the cached List itself but we cast it as an Iterable - // to prevent users from accidentally modifying the cache from outside. - // We are not using an UnmodifiableListView() or anything similar because - // we want to avoid creating a new object for every query. - return result.data as Iterable; - } - - /// Creates a new lazy [Iterable] with all elements that have type [C]. - /// - /// When available, the cached result is used (as in [query]) - /// in constant time. Otherwise, this works exactly the same as - /// [Iterable.whereType], in linear time. - @override - Iterable whereType() { - final result = _cache[C]; - if (result != null) { - return result.data as Iterable; - } - return super.whereType(); - } - - /// Whether type [C] is registered as a cache - bool isRegistered() => _cache.containsKey(C); - - @override - int get length => _backingSet.length; - - @override - Iterator get iterator => _backingSet.iterator; - - @override - Iterable reversed() => _backingSet.reversed(); - - @override - void rebalanceAll() { - _backingSet.rebalanceAll(); - } - - @override - void rebalanceWhere(bool Function(E element) test) { - _backingSet.rebalanceWhere(test); - } - - @override - bool add(E t) { - if (_backingSet.add(t)) { - _cache.forEach((key, value) { - if (value.check(t)) { - value.data.add(t); - } - }); - return true; - } - return false; - } - - @override - bool remove(E e) { - _cache.values.forEach((v) => v.data.remove(e)); - return _backingSet.remove(e); - } - - @override - void clear() { - _cache.values.forEach((v) => v.data.clear()); - _backingSet.clear(); - } - - List _filter() => whereType().toList(); -} - -class _CacheEntry { - final List data; - - _CacheEntry({required this.data}); - - bool check(T t) { - return t is C; - } -} diff --git a/lib/queryable_ordered_set_impl.dart b/lib/queryable_ordered_set_impl.dart new file mode 100644 index 0000000..abda49a --- /dev/null +++ b/lib/queryable_ordered_set_impl.dart @@ -0,0 +1,100 @@ +import 'package:ordered_set/ordered_set.dart'; + +/// This is a mixin to provide the query caching capabilities to both +/// [OrderedSet] implementations. +/// +/// You can [register] a set of queries, i.e., predefined sub-types, whose +/// results, i.e., subsets of this set, are then cached. Since the queries +/// have to be type checks, and types are runtime constants, this can be +/// vastly optimized. +/// +/// You can then filter by type by using the [query] method (or using +/// [whereType]; which is overridden). +/// +/// Note that you can change [strictMode] to allow for querying for unregistered +/// types; if you do so, the registration cost is payed on the first query. +mixin QueryableOrderedSetImpl on OrderedSet { + final Map> _cache = {}; + + @override + void register() { + if (isRegistered()) { + return; + } + _cache[C] = _CacheEntry( + _filter(), + ); + } + + @override + Iterable query() { + final result = _cache[C]; + if (result == null) { + if (strictMode) { + throw 'Cannot query unregistered query $C'; + } else { + register(); + return query(); + } + } + // We are returning the cached List itself but we cast it as an Iterable + // to prevent users from accidentally modifying the cache from outside. + // We are not using an UnmodifiableListView() or anything similar because + // we want to avoid creating a new object for every query. + return result.data as Iterable; + } + + /// Creates a new lazy [Iterable] with all elements that have type [C]. + /// + /// When available, the cached result is used (as in [query]) + /// in constant time. Otherwise, this works exactly the same as + /// [Iterable.whereType], in linear time. + @override + Iterable whereType() { + final result = _cache[C]; + if (result != null) { + return result.data as Iterable; + } + return super.whereType(); + } + + @override + bool isRegistered() => _cache.containsKey(C); + + void onAdd(E t) { + for (final entry in _cache.entries) { + final value = entry.value; + if (value.check(t)) { + value.data.add(t); + } + } + } + + void onRemove(E e) { + for (final entry in _cache.entries) { + final value = entry.value; + if (value.check(e)) { + value.data.remove(e); + } + } + } + + void onClear() { + for (final entry in _cache.entries) { + final value = entry.value; + value.data.clear(); + } + } + + List _filter() => whereType().toList(); +} + +class _CacheEntry { + final List data; + + _CacheEntry(this.data); + + bool check(T t) { + return t is C; + } +} diff --git a/lib/read_only_ordered_set.dart b/lib/read_only_ordered_set.dart new file mode 100644 index 0000000..37ca5c8 --- /dev/null +++ b/lib/read_only_ordered_set.dart @@ -0,0 +1,36 @@ +import 'dart:collection'; + +abstract class ReadOnlyOrderedSet extends IterableMixin { + /// The tree's elements in reversed order; should be cached when possible. + Iterable reversed(); + + /// Controls whether running an unregistered query throws an error or + /// performs just-in-time filtering. + bool get strictMode; + + /// Whether type [C] is registered as a cache + bool isRegistered(); + + /// Adds a new cache for a subtype [C] of [E], allowing you to call [query]. + /// If the cache already exists this operation is a no-op. + /// + /// If the set is not empty, the current elements will be re-sorted. + /// + /// It is recommended to [register] all desired types at the beginning of + /// your application to avoid recomputing the existing elements upon + /// registration. + void register(); + + /// Allow you to find a subset of this set with all the elements `e` for + /// which the condition `e is C` is true. This is equivalent to + /// + /// ```dart + /// orderedSet.whereType() + /// ``` + /// + /// except that it is O(0). + /// + /// Note: you *must* call [register] for every type [C] you desire to use + /// before calling this, or set [strictMode] to false. + Iterable query(); +} diff --git a/pubspec.yaml b/pubspec.yaml index e186761..5eb8d0b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -12,11 +12,11 @@ topics: - ordered-set environment: - sdk: '>=3.4.0 <4.0.0' + sdk: '>=3.6.0 <4.0.0' dev_dependencies: - benchmark_harness: ^2.2.2 - coverage: ^1.8.0 - dartdoc: ^8.0.9+1 - flame_lint: ^1.2.0 - test: ^1.25.7 + benchmark_harness: ^2.3.1 + coverage: ^1.13.1 + dartdoc: ^8.3.3 + flame_lint: ^1.3.0 + test: ^1.26.2 diff --git a/test/comparing_ordered_set_test.dart b/test/comparing_ordered_set_test.dart index c7438cc..11e48b6 100644 --- a/test/comparing_ordered_set_test.dart +++ b/test/comparing_ordered_set_test.dart @@ -118,12 +118,14 @@ void main() { }); test('with repeated priority elements', () { - final a = OrderedSet.comparing((a, b) => (a % 2) - (b % 2)); + final a = OrderedSet.comparing( + compare: (a, b) => (a % 2) - (b % 2), + ); expect(a.addAll([7, 4, 3, 1, 2, 6, 5]), 7); expect(a.length, 7); expect(a.toList().join(), '4267315'); - final b = OrderedSet.comparing((a, b) => 0); + final b = OrderedSet.comparing(compare: (a, b) => 0); expect(b.addAll([7, 4, 3, 1, 2, 6, 5]), 7); expect(a.length, 7); expect(b.toList().join(), '7431265'); @@ -174,7 +176,9 @@ void main() { }); test('keeps track of length when removing', () { - final a = OrderedSet.comparing((a, b) => 0); // no priority + final a = OrderedSet.comparing( + compare: (a, b) => 0, // no priority + ); expect(a.addAll([1, 2, 3, 4]), 4); expect(a.length, 4); @@ -223,7 +227,7 @@ void main() { test('test with custom comparator', () { final a = OrderedSet.comparing( - (a, b) => a.name.compareTo(b.name), + compare: (a, b) => a.name.compareTo(b.name), ); expect(a.add(ComparableObject(1, 'Sunny')), isTrue); expect(a.add(ComparableObject(12, 'Klaus')), isTrue); @@ -235,7 +239,9 @@ void main() { test( 'test items with repeated comparables, maintain insertion order', () { - final a = OrderedSet.comparing((a, b) => (a % 2) - (b % 2)); + final a = OrderedSet.comparing( + compare: (a, b) => (a % 2) - (b % 2), + ); for (var i = 0; i < 10; i++) { expect(a.add(i), isTrue); } @@ -275,7 +281,7 @@ void main() { test('with custom comparator, repeated items and removal', () { final a = OrderedSet.comparing( - (a, b) => -a.priority.compareTo(b.priority), + compare: (a, b) => -a.priority.compareTo(b.priority), ); final a1 = ComparableObject(2, '1'); final a2 = ComparableObject(2, '2'); @@ -321,7 +327,7 @@ void main() { test('removeAll', () { final orderedSet = OrderedSet.comparing( - Comparing.on((e) => e.priority), + compare: Comparing.on((e) => e.priority), ); final a = ComparableObject(0, 'a'); @@ -361,7 +367,7 @@ void main() { group('rebalancing', () { test('rebalanceWhere and rebalanceAll', () { final orderedSet = OrderedSet.comparing( - Comparing.on((e) => e.priority), + compare: Comparing.on((e) => e.priority), ); final a = ComparableObject(0, 'a'); @@ -388,7 +394,7 @@ void main() { group('reversed', () { test('reversed properly invalidates cache', () { final orderedSet = OrderedSet.comparing( - Comparing.on((e) => e.priority), + compare: Comparing.on((e) => e.priority), ); final a = ComparableObject(0, 'a'); diff --git a/test/comparing_test.dart b/test/comparing_test.dart index ec6527d..5216ee7 100644 --- a/test/comparing_test.dart +++ b/test/comparing_test.dart @@ -1,5 +1,6 @@ import 'package:ordered_set/comparing.dart'; import 'package:ordered_set/comparing_ordered_set.dart'; +import 'package:ordered_set/ordered_set.dart'; import 'package:test/test.dart'; import 'comparable_object.dart'; @@ -31,7 +32,7 @@ void main() { }); test('using complex object', () { final set = ComparingOrderedSet( - Comparing.on((o) => o.name), + compare: Comparing.on((o) => o.name), ); set.add(ComparableObject(0, 'd')); set.add(ComparableObject(1, 'b')); @@ -55,7 +56,7 @@ void main() { final c = Comparing.reverse( Comparing.on((t) => t.name), ); - final set = ComparingOrderedSet(c); + final set = OrderedSet.comparing(compare: c); set.add(ComparableObject(0, 'd')); set.add(ComparableObject(1, 'b')); set.add(ComparableObject(2, 'a')); @@ -70,7 +71,7 @@ void main() { (ComparableObject t) => t.priority, (ComparableObject t) => t.name, ]); - final set = ComparingOrderedSet(c); + final set = OrderedSet.comparing(compare: c); set.add(ComparableObject(1, 'b')); set.add(ComparableObject(0, 'b')); set.add(ComparableObject(3, 'a')); diff --git a/test/queryable_comparable_ordered_set_test.dart b/test/queryable_comparable_ordered_set_test.dart index ad979d3..c0ff5ad 100644 --- a/test/queryable_comparable_ordered_set_test.dart +++ b/test/queryable_comparable_ordered_set_test.dart @@ -1,6 +1,5 @@ import 'package:ordered_set/comparing.dart'; import 'package:ordered_set/ordered_set.dart'; -import 'package:ordered_set/queryable_ordered_set.dart'; import 'package:test/test.dart'; abstract class Animal { @@ -291,13 +290,11 @@ void main() { }); } -QueryableOrderedSet _create({ +OrderedSet _create({ bool strictMode = true, }) { - return OrderedSet.queryable( - OrderedSet.comparing( - Comparing.on((e) => e.name), - ), + return OrderedSet.comparing( + compare: Comparing.on((e) => e.name), strictMode: strictMode, ); } diff --git a/test/queryable_priority_ordered_set_test.dart b/test/queryable_priority_ordered_set_test.dart index cab9c1b..12f1918 100644 --- a/test/queryable_priority_ordered_set_test.dart +++ b/test/queryable_priority_ordered_set_test.dart @@ -1,5 +1,4 @@ import 'package:ordered_set/ordered_set.dart'; -import 'package:ordered_set/queryable_ordered_set.dart'; import 'package:test/test.dart'; abstract class Animal { @@ -290,11 +289,11 @@ void main() { }); } -QueryableOrderedSet _create({ +OrderedSet _create({ bool strictMode = true, }) { - return OrderedSet.queryable( - OrderedSet.mapping((e) => e.name), + return OrderedSet.mapping( + (e) => e.name, strictMode: strictMode, ); }