From 314c1e11dff5e0351698e6f82d4c7b399b72ed34 Mon Sep 17 00:00:00 2001 From: Jake Macdonald Date: Tue, 5 Nov 2024 18:06:30 +0000 Subject: [PATCH] use values iterator --- pkgs/collection/CHANGELOG.md | 6 ++---- pkgs/collection/lib/src/equality.dart | 12 +++++++++--- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/pkgs/collection/CHANGELOG.md b/pkgs/collection/CHANGELOG.md index ffac9249..b6a9c82b 100644 --- a/pkgs/collection/CHANGELOG.md +++ b/pkgs/collection/CHANGELOG.md @@ -2,10 +2,8 @@ - Add `IterableMapEntryExtension` for working on `Map` as a list of pairs, using `Map.entries`. -- Use `entries` and `update` in map equality implementations. - - Speeds up all equality checks. - - Speeds up implementations for maps with slow lookup, at a slight cost for - other implementations. +- 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 28874f8d..4ed1c2a5 100644 --- a/pkgs/collection/lib/src/equality.dart +++ b/pkgs/collection/lib/src/equality.dart @@ -325,11 +325,15 @@ class MapEquality implements Equality> { var length = map1.length; if (length != map2.length) return false; Map<_MapEntry, int> equalElementCounts = HashMap(); - for (var MapEntry(:key, :value) in map1.entries) { + var values1 = map1.values.iterator; + for (var key in map1.keys) { + var value = (values1..moveNext()).current; var entry = _MapEntry(this, key, value); equalElementCounts.update(entry, (i) => i + 1, ifAbsent: () => 1); } - for (var MapEntry(:key, :value) in map2.entries) { + final values2 = map2.values.iterator; + for (var key in map2.keys) { + var value = (values2..moveNext()).current; var entry = _MapEntry(this, key, value); var count = equalElementCounts.update(entry, (i) => i - 1, ifAbsent: () => -1); @@ -342,7 +346,9 @@ class MapEquality implements Equality> { int hash(Map? map) { if (map == null) return null.hashCode; var hash = 0; - for (var MapEntry(:key, :value) in map.entries) { + 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(value); hash = (hash + 3 * keyHash + 7 * valueHash) & _hashMask;