在阅读有关Hashtable的Oracle文档时,我发现" 在"哈希冲突"的情况下,单个存储桶存储多个条目,必须按顺序搜索 ",所以我尝试找到顺序返回项目的方法,如果我有两个具有相同哈希的项目,但无法在文档中找到。为了重现这种情况,我尝试编写一个简单的代码,您可以在下面找到它。
Hashtable的一个实例有两个影响其性能的参数:初始容量和负载因子。容量是哈希表中的桶数,初始容量只是创建哈希表时的容量。 请注意,哈希表是打开的:在"哈希冲突"的情况下,单个存储桶存储多个条目,必须按顺序搜索。加载因子是在自动增加容量之前允许哈希表获取的完整程度的度量。初始容量和负载系数参数仅仅是实现的提示。关于何时以及是否调用rehash方法的确切细节是依赖于实现的。
class Key {
public final int mID;
public Key(int id) {
mID = id;
}
@Override
public int hashCode() {
if(mID == 1 || mID == 2) {
System.out.println("Have same hashCode()");
return 5673654;
}
return super.hashCode();
}
};
public class HashtableTest {
public static void main(String... args) {
Hashtable<Key, String> dict = new Hashtable<Key, String>();
dict.put(new Key(1), "One");
dict.put(new Key(2), "Two");
System.out.println(dict.size()); // Prints 2
System.out.println(dict.get(new Key(1))); // Prints null
}
};
在上面的代码中,我尝试向Hashtable添加两个具有相同哈希码的项目(无论如何我认为它们都有:)),为此我创建了我的Key
类并覆盖它&#39; s hashCode
方法,但这没用,因为我甚至无法从Hashtable中获取项目,我认为项目不会按顺序添加。
答案 0 :(得分:6)
Hashtable
(和HashMap
)已经通过存储映射到相同存储桶编号的多个密钥来实现冲突解决。
但是,您还需要覆盖equals
中的Key
方法。对于Hashtable
(或HashMap
)查找映射中已存在的密钥,哈希码用于查找存储区,但equals
用于区分任何不同的密钥。同一桶。由于您不能覆盖equals
,Key
会继承equals
from Object
,{{3}}只会确定这两个对象是否是同一个对象,而不是它们的内容是否相等。
类Object的equals方法实现了对象上最具辨别力的等价关系;也就是说,对于任何非空引用值x和y,当且仅当x和y引用同一对象时,此方法才返回true(x == y的值为true)。
请注意,通常需要在重写此方法时覆盖hashCode方法,以便维护hashCode方法的常规协定,该方法声明相等的对象必须具有相同的哈希代码。
答案 1 :(得分:0)
您还需要实施equals
方法,下面是一个完整的示例:
public class ClientPojo {
private String firstName;
private String lastName;
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getFirstName() {
return this.firstName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getLastName() {
return this.lastName;
}
@Override
public boolean equals(Object obj) {
return obj instanceof ClientPojo
&& this.firstName.equals(((ClientPojo) obj).getFirstName())
&& this.lastName.equals(((ClientPojo) obj).getLastName());
}
@Override
public int hashCode() {
return new org.apache.commons.lang3.builder.HashCodeBuilder(17, 37)
.append(this.firstName)
.append(this.lastName)
.toHashCode();
}
}
org.apache.commons.lang3.builder.HashCodeBuilder
也可以很容易地构建哈希值。
答案 2 :(得分:0)
在您的代码中new Key(1)
和new Key(2)
具有相同的哈希码(== 5673654),因此它们将在相同的存储桶中。
当您通过dict.get(new Key(1))
检索时 - 在这种情况下,new Key(1)
也有相同的HashCode,所以这也将在同一个桶中搜索.// fine
但是之前插入的对象(new Key(1)
和new Key(2)
)不等于此对象(new Key(1)
),所以这不会给出任何记录。您还需要实现equals方法。 / p>
自 -
new Key(1).equals(new Key(1))
//假
new Key(2).equals(new Key(1))
//假