我有一个新类的奇怪行为,我必须覆盖==运算符和hashCode方法。
我会以你为榜样。 假设我们有一个如下所示的Test类:
import 'package:quiver/core.dart';
import 'package:collection/collection.dart';
class Test {
List testList = [];
operator ==(Object other) {
if (other is! Test) return false;
Function deepEq = const DeepCollectionEquality.unordered().equals;
return deepEq(testList, (other as Test).testList);
}
int get hashCode => hashObjects(testList);
}
现在我运行以下代码:
main() {
Test test = new Test();
//test.testList.add([]);
print('Test, hash: ${test.hashCode}');
Test test_2 = new Test();
//test_2.testList.add([]);
print('Test_2, hash: ${test_2.hashCode}');
print("is ${test == test_2} that Test and Test2 are equal");
Function deepEq = const DeepCollectionEquality.unordered().equals;
bool b = deepEq(test, test_2);
print("is $b that Test and Test2 are deep equal");
List l1 = [test];
print('L1 hash: ${l1.hashCode}');
List l2 = [test_2];
print('L2 hash: ${l2.hashCode}');
deepEq = const DeepCollectionEquality.unordered().equals;
b = deepEq(l1, l2);
print("is $b that List1 and List2 are deep equal");
}
上面的代码打印出以下内容,这就是我的预期:
Test, hash: 0
Test_2, hash: 0
is true that Test and Test2 are equal
is true that Test and Test2 are deep equal
L1 hash: 89819481
L2 hash: 414841104
is true that List1 and List2 are deep equal
现在如果我取消注释行:
test.testList.add([]);
test_2.testList.add([]);
并重新运行程序,我有以下结果:
Test, hash: 76603616
Test_2, hash: 386421917
is true that Test and Test2 are equal
is true that Test and Test2 are deep equal
L1 hash: 915458568
L2 hash: 503799923
is false that List1 and List2 are deep equal
这不是我的预期。鉴于DeepCollectionEquality在内部使用hashCode来检查相等性,我可以理解,当遇到List作为主List的组件时,hashObjects使用List hashCode,而不是生成一个读取所有组件的新的hashCode。我不明白为什么测试和测试2被认为是等于List1和List2不是。 这取决于我正在创建哈希码的Iterable中存在多少级内部列表? HashObjects的设计工作方式与此类似,或者应该将其视为错误? 我如何使用hashObjects有什么问题吗?
答案 0 :(得分:0)
你的问题是hashObjects()
没有递归,而且空列表的两个不同实例通常会有不同的哈希值(除非两者都是常量或偶然)。
因此,hashObjects()
的工作方式与平面列表相同,但不适用于列表列表,除非相应的子列表是相同的对象(并且不仅仅是结构上相同的)。
以下示例应说明这一点:
import 'package:quiver/core.dart';
void main() {
var a = [];
var b = [];
var c = [];
print(a.hashCode); // different
print(b.hashCode);
print(hashObjects(a)); // both same, both zero
print(hashObjects(b));
print(hashObjects(a..add(1))); // both same
print(hashObjects(b..add(1)));
print(hashObjects(a..add(c))); // both same, because `c` is identical
print(hashObjects(b..add(c)));
print(hashObjects(a..add([]))); // different, because the two empty
print(hashObjects(b..add([]))); // lists are not identical.
}