44
55import 'dart:collection' ;
66
7+ import 'package:meta/meta.dart' ;
8+
79/// A map whose keys are converted to canonical values of type `C` .
810///
911/// This is useful for using case-insensitive String keys, for example. It's
1012/// more efficient than a [LinkedHashMap] with a custom equality operator
1113/// because it only canonicalizes each key once, rather than doing so for each
1214/// comparison.
13- final class CanonicalizedMap <C , K , V > implements Map <K , V > {
15+ @sealed // TODO: Make `final` when no longer extended.
16+ class CanonicalizedMap <C , K , V > implements Map <K , V > {
1417 final C Function (K ) _canonicalize;
1518
1619 final bool Function (K )? _isValidKeyFn;
@@ -25,10 +28,11 @@ final class CanonicalizedMap<C, K, V> implements Map<K, V> {
2528 /// The [isValidKey] function is called before calling [canonicalize] for
2629 /// methods that take arbitrary objects. It can be used to filter out keys
2730 /// that can't be canonicalized.
28- CanonicalizedMap (C Function (K key) canonicalize,
29- {bool Function (K key)? isValidKey})
30- : _canonicalize = canonicalize,
31- _isValidKeyFn = isValidKey;
31+ CanonicalizedMap (
32+ C Function (K key) canonicalize, {
33+ bool Function (K key)? isValidKey,
34+ }) : _canonicalize = canonicalize,
35+ _isValidKeyFn = isValidKey;
3236
3337 /// Creates a canonicalized map that is initialized with the key/value pairs
3438 /// of [other] .
@@ -39,10 +43,12 @@ final class CanonicalizedMap<C, K, V> implements Map<K, V> {
3943 /// The [isValidKey] function is called before calling [canonicalize] for
4044 /// methods that take arbitrary objects. It can be used to filter out keys
4145 /// that can't be canonicalized.
42- CanonicalizedMap .from (Map <K , V > other, C Function (K key) canonicalize,
43- {bool Function (K key)? isValidKey})
44- : _canonicalize = canonicalize,
45- _isValidKeyFn = isValidKey {
46+ CanonicalizedMap .from (
47+ Map <K , V > other,
48+ C Function (K key) canonicalize, {
49+ bool Function (K key)? isValidKey,
50+ }) : _canonicalize = canonicalize,
51+ _isValidKeyFn = isValidKey {
4652 addAll (other);
4753 }
4854
@@ -56,15 +62,19 @@ final class CanonicalizedMap<C, K, V> implements Map<K, V> {
5662 /// methods that take arbitrary objects. It can be used to filter out keys
5763 /// that can't be canonicalized.
5864 CanonicalizedMap .fromEntries (
59- Iterable <MapEntry <K , V >> entries, C Function (K key) canonicalize,
60- {bool Function (K key)? isValidKey})
61- : _canonicalize = canonicalize,
62- _isValidKeyFn = isValidKey {
65+ Iterable <MapEntry <K , V >> entries,
66+ C Function (K key) canonicalize, {
67+ bool Function (K key)? isValidKey,
68+ }) : _canonicalize = canonicalize,
69+ _isValidKeyFn = isValidKey {
6370 addEntries (entries);
6471 }
6572
6673 CanonicalizedMap ._(
67- this ._canonicalize, this ._isValidKeyFn, Map <C , MapEntry <K , V >> base ) {
74+ this ._canonicalize,
75+ this ._isValidKeyFn,
76+ Map <C , MapEntry <K , V >> base ,
77+ ) {
6878 _base.addAll (base );
6979 }
7080
@@ -92,8 +102,11 @@ final class CanonicalizedMap<C, K, V> implements Map<K, V> {
92102 }
93103
94104 @override
95- void addEntries (Iterable <MapEntry <K , V >> entries) => _base.addEntries (entries
96- .map ((e) => MapEntry (_canonicalize (e.key), MapEntry (e.key, e.value))));
105+ void addEntries (Iterable <MapEntry <K , V >> entries) => _base.addEntries (
106+ entries.map (
107+ (e) => MapEntry (_canonicalize (e.key), MapEntry (e.key, e.value)),
108+ ),
109+ );
97110
98111 @override
99112 Map <K2 , V2 > cast <K2 , V2 >() => _base.cast <K2 , V2 >();
@@ -158,14 +171,16 @@ final class CanonicalizedMap<C, K, V> implements Map<K, V> {
158171
159172 @override
160173 V update (K key, V Function (V ) update, {V Function ()? ifAbsent}) =>
161- _base.update (_canonicalize (key), (pair) {
162- var value = pair.value;
163- var newValue = update (value);
164- if (identical (newValue, value)) return pair;
165- return MapEntry (key, newValue);
166- },
167- ifAbsent:
168- ifAbsent == null ? null : () => MapEntry (key, ifAbsent ())).value;
174+ _base.update (
175+ _canonicalize (key),
176+ (pair) {
177+ var value = pair.value;
178+ var newValue = update (value);
179+ if (identical (newValue, value)) return pair;
180+ return MapEntry (key, newValue);
181+ },
182+ ifAbsent: ifAbsent == null ? null : () => MapEntry (key, ifAbsent ()),
183+ ).value;
169184
170185 @override
171186 void updateAll (V Function (K key, V value) update) =>
@@ -193,5 +208,6 @@ final class CanonicalizedMap<C, K, V> implements Map<K, V> {
193208 /// Creates a `Map<C,V>` (with the canonicalized keys).
194209 /// See [toMap] .
195210 Map <C , V > toMapOfCanonicalKeys () => Map <C , V >.fromEntries (
196- _base.entries.map ((e) => MapEntry <C , V >(e.key, e.value.value)));
211+ _base.entries.map ((e) => MapEntry <C , V >(e.key, e.value.value)),
212+ );
197213}
0 commit comments