diff --git a/pkgs/collection/CHANGELOG.md b/pkgs/collection/CHANGELOG.md index 239efd57..b6a9c82b 100644 --- a/pkgs/collection/CHANGELOG.md +++ b/pkgs/collection/CHANGELOG.md @@ -1,6 +1,9 @@ ## 1.19.1-wip + - Add `IterableMapEntryExtension` for working on `Map` as a list of pairs, using `Map.entries`. +- Optimize equality and hash code for maps by using `update` and a `values` + iterator to avoid extra lookups. ## 1.19.1 diff --git a/pkgs/collection/lib/src/equality.dart b/pkgs/collection/lib/src/equality.dart index 0e1df23d..1e2f02ae 100644 --- a/pkgs/collection/lib/src/equality.dart +++ b/pkgs/collection/lib/src/equality.dart @@ -325,16 +325,19 @@ class MapEquality implements Equality> { var length = map1.length; if (length != map2.length) return false; Map<_MapEntry, int> equalElementCounts = HashMap(); + var values1 = map1.values.iterator; for (var key in map1.keys) { - var entry = _MapEntry(this, key, map1[key]); - var count = equalElementCounts[entry] ?? 0; - equalElementCounts[entry] = count + 1; + var value = (values1..moveNext()).current; + var entry = _MapEntry(this, key, value); + equalElementCounts.update(entry, _addOne, ifAbsent: _one); } + final values2 = map2.values.iterator; for (var key in map2.keys) { - var entry = _MapEntry(this, key, map2[key]); - var count = equalElementCounts[entry]; - if (count == null || count == 0) return false; - equalElementCounts[entry] = count - 1; + var value = (values2..moveNext()).current; + var entry = _MapEntry(this, key, value); + var count = equalElementCounts.update(entry, _subtractOne, + ifAbsent: _negativeOne); + if (count < 0) return false; } return true; } @@ -343,9 +346,11 @@ class MapEquality implements Equality> { int hash(Map? map) { if (map == null) return null.hashCode; var hash = 0; + var values = map.values.iterator; for (var key in map.keys) { + var value = (values..moveNext()).current; var keyHash = _keyEquality.hash(key); - var valueHash = _valueEquality.hash(map[key] as V); + var valueHash = _valueEquality.hash(value); hash = (hash + 3 * keyHash + 7 * valueHash) & _hashMask; } hash = (hash + (hash << 3)) & _hashMask; @@ -489,3 +494,8 @@ class CaseInsensitiveEquality implements Equality { @override bool isValidKey(Object? object) => object is String; } + +int _addOne(int i) => i + 1; +int _subtractOne(int i) => i - 1; +int _one() => 1; +int _negativeOne() => -1;