Dart重写==的同时,还需要重写hashCode

2024-03-03  本文已影响0人  浩然爸

在进行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,从而实现真正的相等。

上一篇 下一篇

猜你喜欢

热点阅读