设置添加重复的项目



当我将同一项目添加到集合中时,如果该项目包含列表,则会重复。

前任: ‍‍‍‍‍

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);
}

最新更新