[英]HashSet allows multiple items with same HashCode
我的HashSet包含多個具有相同HashCode的“ AccessRequests”。 我只希望有一個實例。 我不認為具有相同HashCode的項目可以顯示在HashSet中。 我在這里做錯了什么?
更新:基於這樣的假設:HashSet僅保留一個與列表中的另一個不相等的項目,並且可能我的equals / hash方法需要簡化,因此我更新了問題。 我的HashSet中仍然有多個項目等於Equals。
以下是來自“ AccessRequest”的HashCode和Equals方法
更新:我更新了我的哈希值,等於只具有我需要“等於”的必要字段
@Override
public int hashCode() {
int hash = 5;
hash = 79 * hash + Objects.hashCode(this.targets);
hash = 79 * hash + Objects.hashCode(this.sources);
hash = 79 * hash + Objects.hashCode(this.destinations);
hash = 79 * hash + Objects.hashCode(this.services);
hash = 79 * hash + Objects.hashCode(this.action);
return hash;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final AccessRequest other = (AccessRequest) obj;
if (!Objects.equals(this.action, other.action)) {
return false;
}
if (!Objects.equals(this.targets, other.targets)) {
return false;
}
if (!Objects.equals(this.sources, other.sources)) {
return false;
}
if (!Objects.equals(this.destinations, other.destinations)) {
return false;
}
if (!Objects.equals(this.services, other.services)) {
return false;
}
return true;
}
創建AccessRequest之后,我將它們轉儲到HashSet中並進行迭代:我的HashSet定義如下:
Set<AccessRequest> ars = new HashSet();
ArrayList<AccessRequest> arsAsList = new ArrayList(ars);
for(int position=0;position<arsAsList.size();position++){
AccessRequest fixedAR = arsAsList.get(position);
ArrayList<AccessRequest> comparToList = new ArrayList(ars);
for(int cPosition=0;cPosition<comparToList.size();cPosition++){
AccessRequest nextAR = comparToList.get(cPosition);
if(fixedAR.equals(nextAR)){
System.out.println("position= "+position+" cPosition "+cPosition);
}
}
System.out.println("\n Next AR");
}
以下是輸出:
position= 0 cPosition 0
position= 0 cPosition 5
position= 0 cPosition 6
position= 0 cPosition 14
position= 0 cPosition 24
position= 0 cPosition 32
position= 0 cPosition 39
position= 0 cPosition 40
position= 0 cPosition 43
position= 0 cPosition 77
position= 0 cPosition 96
position= 0 cPosition 97
position= 0 cPosition 99
position= 0 cPosition 109
position= 0 cPosition 111
position= 0 cPosition 115
position= 0 cPosition 173
position= 0 cPosition 182
position= 0 cPosition 187
集合基於equals
方法(1)防止重復。 從javadoc (我強調):
不包含重復元素的集合。 更正式地講,集合不包含元素e1和e2對,例如e1.equals(e2) ,最多不包含一個null元素。
如果您的元素根據其哈希碼應相等,則相應地實現equals
方法(例如,僅比較調用hashCode
的結果)。 請注意,這可能不是最好的主意,因為equals
方法當前會評估更多屬性。
(1):至少是您當前正在使用的HashSet
。
您剛剛觀察到的是哈希碼沖突。 因為哈希碼函數將值從較大的集合(例如,所有可能的String
,有無限數量)映射到較小的集合(例如,所有可能的int
,僅2 ^ 32個不同的值),所以總是會發生沖突。
這就是為什么利用哈希的數據結構始終處理哈希沖突的原因,例如通過實現Open Addressing 。 您可以查看Hash Tables Wiki的“沖突解決”部分,以更好地了解問題:
當散列大量可能密鑰的隨機子集時,散列沖突實際上是不可避免的。 例如,如果將2450個密鑰散列到一百萬個存儲桶中,即使具有完全均勻的隨機分布,則根據生日問題,至少有兩個密鑰散列到同一插槽的機率大約為95%。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.