用自定義的類型作為HashMap的key,必須同時重載hashCode()和equals(),才可以實現在HashMap中的查找自定義鍵。 ...
用自定義的類型作為HashMap的key,必須同時重載hashCode()和equals(),才可以實現在HashMap中的查找自定義鍵。
例如自定義Point類:
public class Point { private int x; private int y; public Point(int x,int y) { this.x = x; this.y = y; } public void setX(int x) { this.x = x; } public int getX() { return x; } public void setY(int y) { this.y = y; } public int getY() { return y; } @Override public String toString() { return "["+x+","+y+"]"; } }View Code
示例:
clusters數據示例:<String, Set<Point>> <用戶,所有簇中心坐標列表>
Point作為Map的鍵:
Map<Point, Set<String>> usersOfCertainPoint = new LinkedHashMap<Point, Set<String>>();//<網格坐標, 聚類中心點為該坐標的所有用戶列表> Iterator<Map.Entry<String, Set<Point>>> iterator = clusters.entrySet().iterator(); while(iterator.hasNext()){ Map.Entry<String, Set<Point>> entry = iterator.next(); for(Point p : entry.getValue()){ if(!usersOfCertainPoint.containsKey(p)){//containsKey()出錯 Set<String> userSet = new HashSet<String>(); userSet.add(entry.getKey()); usersOfCertainPoint.put(p, userSet); }else{ usersOfCertainPoint.get(p).add(entry.getKey()); } } }View Code
錯誤輸出示例:
問題出在Point自動地繼承自基類Object,所以這裡使用Object的hashCode()方法生成散列碼,而它預設是使用對象的地址計算散列碼。因此即使是兩個值相同的Point對象如[4515,-8198],因為其地址不同,所以生成的散列碼不同。
若只重載hashCode(),還是無法正常運行,必須同時重載equals()方法。在HashMap中,查找key的比較順序為:
- 計算對象的hashCode,看在表中是否存在;
- 檢查對應hashCode位置中的對象和當前對象是否相等。
重載hashCode()和equals():
@Override public boolean equals(Object o){ if(this == o)//是否是本類的一個引用 return true; if(!(o instanceof Point)) return false; Point p = (Point)o; return (p.x == this.x) && (p.y == this.y); } @Override public int hashCode(){ int result = 17; result = 31 * result + x; result = 31 * result + y; return result; }View Code
正確輸出示例: