【问题标题】:Java: Hashtable stores multiple items with same hash in one bucketJava:Hashtable在一个桶中存储多个具有相同哈希的项目
【发布时间】:2014-12-04 22:34:13
【问题描述】:

问题描述

在阅读有关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
    }

};

在上面的代码中,我尝试将两个具有相同哈希码的项目添加到哈希表中(无论如何我认为它们有:)),因此我创建了我的 Key 类并覆盖它的 hashCode 方法,但是这是没用的,因为我什至无法从 Hashtable 中获取项目,而且我认为项目不是按顺序添加的。

问题

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

【问题讨论】:

    标签: java hashtable


    【解决方案1】:

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

    但是,您还需要覆盖Key 中的equals 方法。对于Hashtable(或HashMap)来查找map中已经存在的key,哈希码用于查找bucket,但equals用于区分同一个bucket中任何不同的key。因为你没有覆盖equals,所以Key继承了equals from Object,它只判断两个对象是否是同一个对象,而不是它们的内容是否相等。

    Object 类的 equals 方法实现了对象上最有区别的可能等价关系;也就是说,对于任何非空引用值 x 和 y,当且仅当 x 和 y 引用同一个对象(x == y 的值为 true)时,此方法才返回 true。

    请注意,通常需要在任何时候重写 hashCode 方法,以维护 hashCode 方法的一般约定,即相等的对象必须具有相等的哈希码。

    【讨论】:

      【解决方案2】:

      你还需要实现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 还可以很容易地构建散列。

      【讨论】:

        【解决方案3】:

        在您的代码中,new Key(1)new Key(2) 具有相同的哈希码(==5673654),因此它们将进入同一个存储桶。

        当您通过dict.get(new Key(1))-n 检索时,这种情况new Key(1) 也具有相同的HashCode,因此这也会在相同的存储桶中搜索。//fine

        但是之前插入的两个对象(new Key(1)new Key(2))都不等于这个对象(new Key(1))所以这没有记录。你也需要实现equals方法。

        因为-

        new Key(1).equals(new Key(1))//假

        new Key(2).equals(new Key(1))//假

        【讨论】:

          猜你喜欢
          • 2015-07-08
          • 2010-09-18
          • 2012-02-01
          • 2021-03-07
          • 2020-12-29
          • 2019-05-03
          • 2011-10-12
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多