軟件構造筆記——3.5 Equality in ADT and OOP

一、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機制下的等價性
在這裏插入圖片描述
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章