2016-03-24 42 views
0

我想知道ZonedDateTime.hashCode()的執行是否保證與ZonedDateTime.isEqual(...)一致?如果不是,那麼如何計算這樣的散列碼呢?ZonedDateTime hashCode()與isEqual()一致嗎?

編輯

注意,這個問題是關於方法isEqual,不是equals。這不是我的問題中的印刷錯誤。

編輯#2

我問這個的原因是因爲我有一個包含ZonedDateTime對象的類。這個類的實現如下:

public class Foo { 
    private ZonedDateTime dateTime; 

    @Override 
    public boolean equals(Object obj) { 
     // Boilerplate stuff here... 
     final Foo other = (Foo)obj; 
     return (... && dateTime.isEqual(other.dateTime) && ...); 
    } 

    @Override 
    public int hashCode() { 
     // What do I need to put here so that my implementation of 
     // hashCode is consistent with my implementation of equals? 
     return Objects.hashCode(..., dateTime.?, ...); 
    } 
} 

正如你可以,我打電話給我的執行equalsisEqual方法,因爲我想兩個對象當存儲的時間指向比較平等的實現中看到的同一時刻。我可以在執行hashCode時做些什麼,以使Foo類符合hashCodeequals一致的要求?

+0

你有什麼理由不這樣想嗎?如果是這種情況,應該適當記錄。 – Tunaki

+0

你真的需要解釋你爲什麼認爲這可能是這種情況。否則,這個問題很可能成爲StackOverflow的焦點。 –

+0

@fge不,語言規範只保證'hashCode'方法與'equals'一致。我詢問它是否符合另一種稱爲['isEqual']的方法(https://docs.oracle.com/javase/8/docs/api/java/time/chrono/ChronoZonedDateTime.html#isEqual-java .time.chrono.ChronoZonedDateTime-),它產生了一個不同的結果'equals'。他們是兩個不同的問題。 –

回答

3

isEqual()方法的Javadoc說

這相當於使用dateTime1.toInstant().equals(dateTime2.toInstant());

所以如果你想計算一個與這種方法一致的哈希碼,你將不得不使用zdt.toInstant().hashCode()。那麼你的Foo.hashCode()將與你的Foo.equals()一致。

+0

好吧,我的upvote,但那麼問題出現爲什麼OP使用'ZonedDateTime'而不是簡單使用'Instant'操作? ;-)沒有'ZonedDateTime',程序員的生活可能會更容易。 –

+0

@MenoHochschild我希望公共界面具有表現力。當某人獲得或設定時間時,我希望他們明確地知道/指定時區。我還需要將時間序列化爲格式爲「yyDDHHmmss」的字符串(帶有隱式UTC時區)。據我所知,沒有通過DateTime類之一就無法序列化/反序列化一個瞬間。所以是的,我可以在後臺存儲即時消息,但必須在公共接口和序列化/反序列化中來回轉換。看起來像很多額外的工作很少有好處。 –

+1

@JeffG嗯,我承認'ZonedDateTime'不是我個人的偏好,因爲它有一個強大的趨勢,使事情比他們更復雜(也參見這個整個問題和答案的東西)。正如我的經驗表明的那樣,「Instant」和「ZoneId」的組合通常就足夠了,這裏也足夠用於序列化爲日期時間字符串。你認爲這是不可能的,但它是 - 只需設置一個帶時區信息的格式化程序。並且'ZonedDateTime'也需要這樣一個格式化程序(用於JSON?)。將複雜的東西分成幾個簡單的組件往往更有幫助。 –

2

關於你的問題有關方法isEqual()

此法無關與Object - 方法equals()hashCode()。爲了避免混淆,可以更好地將其重命名爲isSimultaneous(),並且使即時比較更清晰。 使這種相似命名方法與hashCode()保持一致的關係毫無意義。

當然,如果兩個ZonedDateTime -objects具有相同的即時然後根據isEqual()比較將產生true,但散列碼通常是不同的,由於不同的本地時間戳。您可能會認爲這是hashCode()isEqual()的不一致,但這不是重點。

方法isEqual()在您使用散列圖查找的任何上下文中根本不相關。

反之,方法hashCode()(或任何計算出來的哈希碼),如果您使用的方法isEqual()是不相關的。

許多downvoters的反應(也是我對你的問題和你的downvote的第一個誤解表明,這兩種方法(equals()isEqual())聽起來非常相似但具有非常不同的含義的事實存在很多混淆的可能性。

+0

@JeffG好吧,我已經更新了我的問題。 –

+0

所以我認爲你的答案可以概括爲:「不,'hashCode'不能保證與'isEqual'一致。那是對的嗎? –

+0

@JeffG我已經編輯了我的答案。不要用'isEqual()'查找'hashCode()'的任何一致性。現在對你更清楚了嗎? –

1

閱讀兩種方法的源代碼:

  • isEqual method比較ZonedDateTime實例以查看它們是否代表(因爲曆元即,等於秒和等於納秒)在同一時刻。

  • hashCode method of ZonedDateTime通過對dateTime,offsetzone的哈希碼進行XOR運算來計算。

沒有辦法預計這兩者可以保持一致,因爲它們會考慮實例的非常不同的屬性。

+1

好的,這回答了我的問題的第一部分。你碰巧知道第二個答案嗎?例如,'ZonedDateTime.toInstant()。hashCode()'會產生一個與isEqual()'一致的散列碼? –

+0

'Instant.hashCode()'計算秒和納秒的散列值。再次,只需通過[閱讀源代碼]回答(http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8-b132/java/time/Instant.java#1314) 。請注意'Instant'沒有'isEqual'方法。 –