2012-05-06 71 views
1

我已經實現了一個類來模擬java中的有理數,它有兩個整數來模擬分子和分母。我需要重寫Object的哈希碼方法,所以相同的數字具有相同的哈希碼。有理數的散列碼

我定義我的equals()方法是這樣的:

public boolean equals(Object obj) { 
    Racional r = null; 
    if (obj instanceof Racional) { 
     r = (Racional) obj; 
    } else { 
     return false; 
    } 
    return r.getDenominador() * this.numerador == r.getNumerador() * this.denominador; 
} 

對此:

將返回分子分母*是一個好方法嗎?

如果等價的有理數(如1/4和2/8)返回相同的哈希碼?

+1

你可以計算哈希碼,即使對象的值是2/8的哈希碼進行計算,以1/4 –

+0

是這樣之前總是簡化,但不會是不必要的複雜性hashCode方法補充的嗎? –

+0

@EugenioCuevas捕獲可能防止異常通常被認爲是不好的做法(投擲/捕獲異常是一個耗時的操作)。通常建議在轉換之前使用'if(obj instanceof Racional)'來防止'ClassCastException's。 – Jeffrey

回答

4

這一切都取決於你如何實現你的equals方法。如果obj1.equals(obj2)true,obj1.hashCode() == obj2.hashCode()也應該是true。我可能會使用new Double((double) numerator/denominator).hashCode()作爲我的散列,但您的要求可能不允許。

/編輯
使用numerator * denominator爲您的散列將是一個無效的方法給你的equals方法。使用1/42/8,1/4.equals(2/8)的示例將返回true,但1/4.hashCode() == 2/8.hashCode()將評估爲4 == 16,並返回false

+0

我已經添加了我已經定義的equals方法,爲什麼hashcode方法依賴於它? –

+0

@EugenioCuevas因爲這是['hashCode'](http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#hashCode())方法的定義方式。 – Jeffrey

+0

我試過你的解決方案,只有缺陷我期待是一個異常或獲取無限或NaN值的哈希碼的東西,但事實證明無限也有一個哈希碼,所以完美!謝謝! –

0

建議是這樣:

37*numerator + 13* denominator 

的哈希碼,而這些都是素數。

我認爲1/4和2/8是不同的,除非你有一個積極的規範化政策。但這取決於你。確保你記錄良好的行爲。

更新: 您需要決定平等意味着什麼。我會先正常化,然後寫:

return this.numerator == r.numerator && this.denominator == r.denominator 
2

如果等價的有理數(如1/4和2/8)返回相同的哈希碼?

由於您equals()方法返回true 1/4和2/8,the two numbers must have the same hash code

實現此目的的一種方法是簡化分數(例如,在施工時)。這可以通過將分子和分母除以GCD來完成。一旦你這樣做,任何合理的功能都可以完成這項工作。