开发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方法才能达到去重比较的效果。