diff --git a/lib/src/equatable_utils.dart b/lib/src/equatable_utils.dart index 4a18c5b7..e0ae8dd2 100644 --- a/lib/src/equatable_utils.dart +++ b/lib/src/equatable_utils.dart @@ -1,3 +1,5 @@ +import 'dart:collection'; + import 'package:collection/collection.dart'; import 'package:equatable/equatable.dart'; @@ -46,6 +48,11 @@ int _combine(int hash, dynamic object) { }); return hash; } + if (object is Set && object is! SplayTreeSet) { + // this is needed to have a consistent iteration order so that the produced + // hash is consistent independently of the Set insertion order + object = SplayTreeSet.from(object); + } if (object is Iterable) { for (final value in object) { hash = hash ^ _combine(hash, value); diff --git a/test/equatable_test.dart b/test/equatable_test.dart index 40b326b3..0bffe89c 100644 --- a/test/equatable_test.dart +++ b/test/equatable_test.dart @@ -968,6 +968,17 @@ void main() { expect(instanceA.hashCode == instanceB.hashCode, true); }); + test('should return when Set values are same but in different order', () { + final instanceA = SimpleEquatable>( + Set.from(['A', 'B']), + ); + final instanceB = SimpleEquatable>( + Set.from(['B', 'A']), + ); + expect(instanceA == instanceB, true); + expect(instanceA.hashCode == instanceB.hashCode, true); + }); + test('should return when values are different', () { final instanceA = SimpleEquatable>( Set.from(['A', 'B']),