软件构造笔记——3.5 Equality in ADT and OOP

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/lll_90/article/details/89264286

一、ADT的等价性主要通过三种方式定义:
1.AF: R → A某数据结构所映射的抽象值相同,
即 AF(a)=AF(b)
2.a与b等价,倘若a与b在同一个等价类中(a与b满足某自反,对称,传递关系)
3.从观察角度对两个对象的任何操作都会得到相同结果。
二、== 与. equals()区别
比较的是内存地址;
equals()比较的是对象的内容
tips:在没有被override 的equals()中对象默认继承了父类Object的equals()方法,作用同

因此,必要时得重写类的equals()与hashCode()。但是,得注意方法的签名必须与被重写的父类方法保持一致。
举个例子:
此处与父类方法中的参数列表不同,所以达到override的效果输出false
如下修改更佳:
在这里插入图片描述输出true。
注意:除了用于实现equals()方法,尽可能避免使用 instanceof和getClass()在运行
时检测对象的类型(动态检查),存在安全隐患,
再举一例,此处发生了等价不一致问题。
在这里插入图片描述输出三、重写override的要求
1.满足等价性(自反,对称,传递)
2.一致性,在比较中用到的信息没有被修改的情况下,多次比较结果应始终相同
3.使用equals方法判定相等的两个对象,其
hashCode必须产生相同的结果。
4. 空值处理:与null比较,必须返回false. eg. 对任意非空引用x, x.equals(null) 返回false.
举个反栗:
上述代码不满足等价关系的传递性。
当a=5, b=0, c=-5时,有等价关系对a与b, b与c,但是a与b不等价。可见,这种等价关系是不满足传递性。
四、HashCode原理说明
如下图,键值对中的key被映射为hashcode,对应到数组的index, hashcode决定了数据被存储到数组的那个位置。当多个key散列到同一个index时(冲突),哈希表维护一个列表来记录这些键值对(bucket)
在这里插入图片描述查询过程:利用hashCode()产生的hashcode确定slot(index),再用equals()方法在bucket中找到匹配的key。

五、hashCode()重写要求
1.只要比较操作用到的信息没有被修改,那么对这同一个对象调用多次,hashCode()方法必须始终返回相同整数。(不要求程序的多次执行时相同)除非对象可变,否则hashcode不能修改。
2. 如果equals比较相等,则要求hashcode相
等;如果equals不等,则hashcode是否相等均可,但最好不等(提升性能)
3.因为大部分语言中都是采用对象的内存地址作为默认hashcode,构造hashcode时考虑对象的所有字段,以避免不相等对象产生相同hashcode
java中提供了Objects.hash()方法,它会根据多个字段产生hashCode()
六、等价性在可变类型中的演绎
可变类型中的等价性分为两种:
1.观察等价:在不改变对象状态的情况下(不使用mutator),无法区分对象
emm,可以理解为通过各个observer方法获得的结果是一样的
2.行为等价:改变一个对象而不改变另外一个时,仍然无法区分对象
emm,也就是两个引用指向了同一个对象
对于可变类型使用观察等价会带来一些bug。
下面举个栗子:
在这里插入图片描述输出Collections实现的是观察等价,当集合元素相同时,两者是等价的,但是当集合内元素发生变化时,便产生了等价不一致问题,如下:
在这里插入图片描述输出如图所示上述问题产生的原因是hashCode会随着内容的变化而变化,使引用对应bucket的index发生了变化;但是放在Bucket中的HashSet并没有发生变化,反而使存放在原来位置的hashSet丢失了。因而打破了rep的不变性。
所以,可变类型应该Equals()应该实现行为等价,直接继承Object类的equals()和hashCode()。
七、最后是Autoboxing机制下的等价性
在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/lll_90/article/details/89264286
ADT