天天看點

java性能優化方案9——優化自定義hasCode()方法和equals()方法

9、優化自定義hasCode()方法和equals()方法

在不能使用EnumMap的情況下,至少也要優化 hashCode() 和 equals() 方法。一個好的 hashCode() 方法是很有必要的,因為它能防止對高開銷 equals() 方法多餘的調用。

在每個類的繼承結構中,需要容易接受的簡單對象。讓我們看一下jOOQ的 org.jooq.Table 是如何實作的?

最簡單、快速的 hashCode() 實作方法如下:

// AbstractTable一個通用Table的基礎實作:

@Override

public int hashCode() {

}

name即為表名。我們甚至不需要考慮schema或者其它表屬性,因為表名在資料庫中通常是唯一的。并且變量 name 是一個字元串,它本身早就已經緩存了一個 hashCode() 值。

這段代碼中注釋十分重要,因繼承自 AbstractQueryPart 的 AbstractTable 是任意抽象文法樹元素的基本實作。普通抽象文法樹元素并沒有任何屬性,是以不能對優化 hashCode() 方法實作抱有任何幻想。覆寫後的 hashCode() 方法如下:

// AbstractQueryPart一個通用抽象文法樹基礎實作:

換句話說,要觸發整個SQL渲染工作流程(rendering workflow)來計算一個普通抽象文法樹元素的hash代碼。

equals() 方法則更加有趣:

// AbstractTable通用表的基礎實作:

public boolean equals(Object that) {

首先,不要過早使用 equals() 方法(不僅在N.O.P.E.中),如果:

• this == argument

• this“不相容:參數

注意:如果我們過早使用 instanceof 來檢驗相容類型的話,後面的條件其實包含了argument == null。我在以前的部落格中已經對這一點進行了說明,請參考10個精妙的Java編碼最佳實踐。

在我們對以上幾種情況的比較結束後,應該能得出部分結論。比如jOOQ的 Table.equals() 方法說明是,用來比較兩張表是否相同。不論具體實作類型如何,它們必須要有相同的字段名。比如下面兩個元素是不可能相同的:

• com.example.generated.Tables.MY_TABLE

• DSL.tableByName(“MY_OTHER_TABLE”)

如果我們能友善地判斷傳入參數是否等于執行個體本身(this),就可以在傳回結果為 false 的情況下放棄操作。如果傳回結果為 true,我們還可以進一步對父類(super)實作進行判斷。在比較過的大多數對象都不等的情況下,我們可以盡早結束方法來節省CPU的執行時間。

一些對象的相似度比其它對象更高。

在jOOQ中,大多數的表執行個體是由jOOQ的代碼生成器生成的,這些執行個體的 equals() 方法都經過了深度優化。而數十種其它的表類型(衍生表 (derived tables)、表值函數(table-valued functions)、數組表(array tables)、連接配接表(joined tables)、資料透視表(pivot tables)、公用表表達式(common table expressions)等,則保持 equals() 方法的基本實作。