在进行dart编码,通过Android Studio快捷键进行重写==时,会同时让你重写hashCode,很多人会疑惑为什么要重写hashCode,因为我只要重写了==,就可以正确的进行判断,因此认为不需要重写hashCode。
main(List<String> args) {
Person p1 = Person('aa');
Person p2 = Person('aa');
print(p1 == p2);
}
class Person {
final String name;
Person(this.name);
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is Person && runtimeType == other.runtimeType && name == other.name;
}
运行结果为:true
通过运行结果来看,确实可以判断两个对象是否相等,然而这个相等却不是真正意义上的相等,当我们使用Set时,便会发现问题。
Set set = Set();
set.add(p1);
set.add(p2);
print(set);
运行结果:{Instance of 'Person', Instance of 'Person'}
此时set中存储了两个Person对象,按照我们的期望,此时set中应该只有一个Person对象才对,问题就在hashCode。
Set set = Set();
set.add(p1);
set.add(p2);
print(p1.hashCode);
print(p2.hashCode);
print(set);
结果:
p1.hashCode = 1052511799
p2.hashCode = 307180047
{Instance of 'Person', Instance of 'Person'}
通过打印结果可以看出,两个Person对象的hashCode是不相等的,set在插入数据时,除了进行==判断外,还会对比hashCode是否相同。因此,set认为,他们是两个不同的对象,要解决这个问题,就需要重写hashCode。
main(List<String> args) {
Person p1 = Person('aa');
Person p2 = Person('aa');
print(p1 == p2);
Set set = Set();
set.add(p1);
set.add(p2);
print('p1.hashCode = ${p1.hashCode}');
print('p2.hashCode = ${p2.hashCode}');
print(set);
}
class Person {
final String name;
Person(this.name);
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is Person && runtimeType == other.runtimeType && name == other.name;
@override
int get hashCode => name.hashCode;
}
结果:
p1.hashCode = 813790094
p2.hashCode = 813790094
{Instance of 'Person'}
此时,便得到了我们期望的结果。
但是,如果对象中包含List/Map需要如何处理?List/Map的Equal判断可以使用系统的listEquals(a, b)
/mapEquals(a, b)
方法。但是hashCode没有找到对应的方法,因此,我们需要自己写一个
class Person {
final String name;
Person(this.name);
List list = [];
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is Person &&
runtimeType == other.runtimeType &&
name == other.name &&
listEquals(list, other.list);
@override
int get hashCode => name.hashCode ^ listHashCode(list);
}
int listHashCode(List<dynamic> list) {
int hashCode = 0;
list.forEach((element) {
hashCode = hashCode ^ element.hashCode;
});
return hashCode;
}
main(List<String> args) {
Person p1 = Person('aa');
p1.list.add('a');
Person p2 = Person('aa');
p2.list.add('a');
Set set = Set();
set.add(p1);
set.add(p2);
print('p1.hashCode = ${p1.hashCode}');
print('p2.hashCode = ${p2.hashCode}');
print(set);
}
结果:
p1.hashCode = 984606668
p2.hashCode = 984606668
{Instance of 'Person'}
所以,重写==时,必须要重写hashCode,从而实现真正的相等。