Dart对象重写==和hashcode方法实现对象比较

39 篇文章 1 订阅

开发Flutter项目的时候,可能遇到集合去重对象的情况,如果是Java,那直接对象重写equals和hashcode方法即可,但是Dart呢?

demo去重测试:

main(List<String> args) {
  /// 整数、字符串利用List,Set去重没有问题
  List l1 = [1, 2, 3];
  List l2 = ["1", "2", "3"];
  if (l1.contains(1)) {
    print('整数对比,已存在');
  }
  if (l2.contains("1")) {
    print('字符串对比,已存在');
  }
​
  List l3 = [
    Student("张三", 20),
    Student("李四", 20),
    Student("王五", 20),
  ];
  /// 没有输出,说明2个不同对象,内容一样但不能去重
  if (l3.contains(Student("张三", 20))) {
    print('类对比,已存在');
  }
​
  Student s1 = Student("张三", 20);
  List l4 = [
    s1,
    Student("李四", 20),
    Student("王五", 20),
  ];
  /// 输出,说明是同个对象可以使用List、Set去重
  if (l4.contains(s1)) {
    print('类对比,已存在');
  }
​
  /// 那dart怎么利用List、Set去重对象???
  /// 当然不是遍历取属性一一比对
  /// 跟Java一样在对象里面重写equals和hashcode方法???
}
​
class Student {
  String name;
  int age;
​
  Student(this.name, this.age);
}

看看集合的contains方法:

/// 集合的contains方法,都是Iterable类的
/// 利用==比较
bool contains(Object? element) {
    for (E e in this) {
      if (e == element) return true;
    }
    return false;
}

集合元素的比较是利用Object的==,接着看看Object的==和hashcode:

/// The equality operator.
  ///
  /// The default behavior for all [Object]s is to return true if and
  /// only if this object and [other] are the same object.
  ///
  /// Override this method to specify a different equality relation on
  /// a class. The overriding method must still be an equivalence relation.
  /// That is, it must be:
  ///
  ///  * Total: It must return a boolean for all arguments. It should never throw.
  ///
  ///  * Reflexive: For all objects `o`, `o == o` must be true.
  ///
  ///  * Symmetric: For all objects `o1` and `o2`, `o1 == o2` and `o2 == o1` must
  ///    either both be true, or both be false.
  ///
  ///  * Transitive: For all objects `o1`, `o2`, and `o3`, if `o1 == o2` and
  ///    `o2 == o3` are true, then `o1 == o3` must be true.
  ///
  /// The method should also be consistent over time,
  /// so whether two objects are equal should only change
  /// if at least one of the objects was modified.
  ///
  /// If a subclass overrides the equality operator, it should override
  /// the [hashCode] method as well to maintain consistency.
  external bool operator ==(Object other);
​
  /// The hash code for this object.
  ///
  /// A hash code is a single integer which represents the state of the object
  /// that affects [operator ==] comparisons.
  ///
  /// All objects have hash codes.
  /// The default hash code implemented by [Object]
  /// represents only the identity of the object,
  /// the same way as the default [operator ==] implementation only considers objects
  /// equal if they are identical (see [identityHashCode]).
  ///
  /// If [operator ==] is overridden to use the object state instead,
  /// the hash code must also be changed to represent that state,
  /// otherwise the object cannot be used in hash based data structures
  /// like the default [Set] and [Map] implementations.
  ///
  /// Hash codes must be the same for objects that are equal to each other
  /// according to [operator ==].
  /// The hash code of an object should only change if the object changes
  /// in a way that affects equality.
  /// There are no further requirements for the hash codes.
  /// They need not be consistent between executions of the same program
  /// and there are no distribution guarantees.
  ///
  /// Objects that are not equal are allowed to have the same hash code.
  /// It is even technically allowed that all instances have the same hash code,
  /// but if clashes happen too often,
  /// it may reduce the efficiency of hash-based data structures
  /// like [HashSet] or [HashMap].
  ///
  /// If a subclass overrides [hashCode], it should override the
  /// [operator ==] operator as well to maintain consistency.
  external int get hashCode;

可以翻译一下,默认Object的==是利用hashCode进行比较,跟Java一样,然后如果要实现dart对象的比较,可以重写==和hashCode,案例如下:

main(List<String> args) {
  Set<Student> set1 = new Set();
  set1.addAll([Student("张三", 20), Student("李四", 20), Student("王五", 20)]);
  /// 这里新new了张三,但是还是能输出,说明是通过对象的值进行比较的,可以利用contains去重了
  if (set1.contains(Student("张三", 20))) {
    print('类对比,已存在');
  }
}
​
class Student {
  String name;
  int age;
​
  Student(this.name, this.age);
​
  @override
  bool operator ==(Object other) {
    if (identical(this, other)) return true;
    if (other is Student) {
      return runtimeType == other.runtimeType &&
          name == other.name &&
          age == other.age;
    } else {
      return false;
    }
  }
​
  @override
  int get hashCode {
    var result = 17;
    result = 37 * result + name.hashCode;
    result = 37 * result + age.hashCode;
    return result;
  }
}

如果对象里面属性是对象,嵌套对象的情况下,都需要重写==和hashcode方法才能达到去重比较的效果。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wzq_55552

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值