Java:Hashtable在一个存储桶中存储具有相同散列的多个项目

时间:2014-10-09 21:01:57

标签: java hashtable

问题描述

在阅读有关Hashtable的Oracle文档时,我发现" 在"哈希冲突"的情况下,单个存储桶存储多个条目,必须按顺序搜索 ",所以我尝试找到顺序返回项目的方法,如果我有两个具有相同哈希的项目,但无法在文档中找到。为了重现这种情况,我尝试编写一个简单的代码,您可以在下面找到它。

Oracle Documentation about Hashtable

  

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中获取项目,我认为项目不会按顺序添加。

问题

  1. 如何在一个存储桶中模拟存储多个条目的情况? (为了更深入地了解这项工作的方式)
  2. 如何访问Hashtable中按顺序存储的项目?

3 个答案:

答案 0 :(得分:6)

Hashtable(和HashMap)已经通过存储映射到相同存储桶编号的多个密钥来实现冲突解决。

但是,您还需要覆盖equals中的Key方法。对于Hashtable(或HashMap)查找映射中已存在的密钥,哈希码用于查找存储区,但equals用于区分任何不同的密钥。同一桶。由于您不能覆盖equalsKey会继承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)) //假