2012-08-24 64 views
2

所以,我試圖用HashMap將我自己的Object映射到String值。我的目標是低於(有一些代碼簡潔,刪除)Java HashMap和key對象的問題我自己推出

public class RouteHeadsignPair { 
    String route; 
    String headsign; 

    public RouteHeadsignPair(String n_route, String n_headsign) { 
     route = n_route.toLowerCase(); 
     headsign = n_headsign.toLowerCase(); 
    } 

    public String getRoute() { 
     return route; 
    } 

    public String getHeadsign() { 
     return headsign; 
    } 

    public boolean equals(RouteHeadsignPair other) { 
     return(other.getRoute().equals(route) && other.getHeadsign().equals(headsign)); 
    } 

    public int hashCode() { 
     return(route.hashCode()); 
    } 
} 

我從一個文本文件映射將數據裝入串一串這些對象。稍後,基於(獨立)用戶輸入,我嘗試使用RouteHeadsignPair對象查詢HashMap。 containsKey()返回false,get()返回null,就好像我從未將鍵添加到地圖中一樣。但是,奇怪的是,如果我用下面的代碼(其中newKey是從用戶輸入的RouteHeadsignPair製造)

RouteHeadsignPair foundKey = null; 
Iterator<RouteHeadsignPair> keysInMap = routeHeadsignToStopIdMap.keySet().iterator(); 
while(keysInMap.hasNext()) { 
    RouteHeadsignPair currKey = keysInMap.next(); 

    if(currKey.equals(newKey)) { 
     System.err.println("Did find a key with an equals() == true!"); 
     foundKey = currKey; 
    } 
} 

System.err.println("Value in map? " + routeHeadsignToStopIdMap.containsKey(newKey) + "(hashcode = " + newKey.hashCode() + 
     ", equals = " + newKey.equals(foundKey) + ")"); 
System.err.println("foundKey in map? " + routeHeadsignToStopIdMap.containsKey(foundKey) + "(hashcode = " + foundKey.hashCode() + 
     ", equals = " + foundKey.equals(newKey) + ")"); 

我的代碼格式道歉迭代在地圖上,這晚,我越來越暴躁

我得到以下輸出

Did find a key with an equals() == true! 

然後

Value in map? false(hashcode = 1695, equals = true) 
foundKey in map? true(hashcode = 1695, equals = true) 

因此,如果我遍歷鍵並查找返回equals()的鍵,我確實找到了一個,而這兩個鍵的hashCode()都是相同的。如果hashCode()newKeyfoundKeyfoundKey.equals(newKey)返回值相同,則不應該HashMap.get(key)返回值並且containsKey()返回true?我在這裏做錯了什麼?

回答

9

你不是壓倒性的Object.equals - 你是超載它因爲參數類型。你的診斷代碼調用你的超載,但地圖代碼不(因爲它不知道它)。

如果使用@Override註解,如果你不能正確地重寫的東西,你會得到一個錯誤,你需要的

public boolean equals(Object other) 

簽名的方法。

您需要先檢查other是否是RouteHeadSignPair的實例,然後進行強制轉換。如果使RouteHeadSignPair級決賽中,您將不必擔心它是否是完全相同的類等

請注意,您的哈希碼將不必要的碰撞,順便說一句 - 如果你同時使用routeheadSign哈希來生成你的哈希碼,它可以幫助你的地圖查找更高效。 (如果有幾個實例具有相同的路線但頭標不同,如果地圖在查找某個鍵時不需要檢查它們是否相等,則很有用。)

+0

我還建議他添加空值檢查或反向等於()調用 –

+0

@EugenMartynov:我不確定你的意思是「反向調用」,但是,還有更多事情要做。將編輯。 –

+0

贏家就是你!我需要刷新Java ... – Ivan