当我将同一项目添加到集合中时,如果该项目包含列表,则会重复。
前任:
main() {
print('equales ${Foo([]) == Foo([])}');
Set<Foo> set = {};
set.add(Foo([]));
print("set.length = ${set.length}");
set.add(Foo([]));
print("set.length = ${set.length}");
}
class Foo {
List<int> ints;
Foo(this.ints);
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is Foo &&
runtimeType == other.runtimeType &&
listEquals(ints, other.ints);
@override
int get hashCode => ints.hashCode;
}
输出:
equales true
set.length = 1
set.length = 2
您的代码为 true,但每次您将新的 List [] 传递给具有不同哈希代码的 Set 时。而不是检查列表的哈希代码,使用枚举类检查相等性。
main() {
print('equales ${Foo([]) == Foo([])}');
print('list -> ${[] == []}');
Set<Foo> set = {};
set.add(Foo([], fooType: FooType.HAPPY));
print("set.length = ${set.length}");
set.add(Foo([], fooType: FooType.HAPPY));
print("set.length = ${set.length}");
set.add(Foo([], fooType: FooType.SAD));
print("set.length = ${set.length}");
}
class Foo {
List<int> ints;
FooType fooType;
Foo(this.ints, {this.fooType});
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is Foo &&
runtimeType == other.runtimeType &&
listEquals(ints, other.ints);
@override
int get hashCode => fooType.hashCode;
}
enum FooType { HAPPY, SAD }
输出:
equales true
list -> false
set.length = 1
set.length = 1
set.length = 2
希望它会有用
您的哈希代码方法不正确,https://api.dartlang.org/stable/2.4.1/dart-core/Object/hashCode.html:
对于根据运算符 == 彼此相等的对象,哈希代码必须相同。
List 不会覆盖默认的 == 和 hashCode,这意味着它们基于身份:
main() {
print('${[] == []}'); // false
print('${[].hashCode == [].hashCode}'); // false
}
与List
不同,Set
使用hashCode
来检查相等性
默认情况下,在 dart 中,列表的hashCode
返回其引用,这在本例中是无用的。
因此,您必须使用DeepCollectionEquality().hash(list)
或者如果顺序对于hashCode
实现DeepCollectionEquality.unordered().hash(list)
不重要。
和DeepCollectionEquality().equals(list)
或者顺序是否不重要DeepCollectionEquality.unordered().equals(list)
所以上面例子的工作代码是:
import 'package:collection/collection.dart';
class Foo {
List<int> ints;
Foo(this.ints);
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is Foo &&
runtimeType == other.runtimeType &&
DeepCollectionEquality().equals(ints, other.ints); //the same as listEquals(ints, other.ints)
@override
int get hashCode => DeepCollectionEquality().hash(ints);
}