开发Flutter项目的时候,可能遇到集合去重对象的情况,如果是Java,那直接对象重写equals和hashcode方法即可,但是Dart呢?
demo去重测试:
main(Listargs) { /// 整数、字符串利用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(Listargs) { Set 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方法才能达到去重比较的效果。



