【问题标题】:Why does resizing takes place if all the elements are ended in same bucked?如果所有元素都以相同的顺序结束,为什么要调整大小?
【发布时间】:2019-07-08 06:19:07
【问题描述】:

我编写了下面的代码来测试当所有元素都在同一个桶中结束时 hashmap 的行为:-

public class DerivedMain {

int data = 10;

@Override
public int hashCode() {
    return data;
}

public static void main(String[] args) {

    HashMap m = new HashMap();
    for(int i=0;i<20;i++) {
        m.put(i, i);
    }

    Field tableField = null;
    try {
        tableField = HashMap.class.getDeclaredField("table");
    } catch (NoSuchFieldException | SecurityException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    tableField.setAccessible(true);
    Object[] table = null;
    try {
        table = (Object[]) tableField.get(m);
    } catch (IllegalArgumentException | IllegalAccessException e) 
            {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    System.out.println(table == null ? 0 : table.length);
}

}

我得到以下输出:- 32

为什么即使所有元素都在同一个存储桶中结束,也会发生大小调整?

【问题讨论】:

    标签: java reflection hashmap hashtable


    【解决方案1】:

    因为 HashMap 就是这样工作的:

    当哈希表中的条目数超过负载因子与当前容量的乘积时,重新哈希表。

    HashMap 只知道,一旦达到限制,冲突的概率就会变得太高,它必须重新哈希以降低该概率并为将来的条目留出空间。它假定 hashCode 的实现很好,并且绝对无法知道冲突是由真正的坏运气引起的,还是由 hashCode 的糟糕实现引起的。

    【讨论】:

      【解决方案2】:

      你可以调试你的代码,然后你会发现你的类'DerivedMain'中定义的'hashcode'方法永远不会被调用,所以所有的元素都不在同一个桶中。但是真正输出32的原因是hashmap的size(20)大于阈值(table.size * loadfactor)。如果你想知道hashmap的更多工作细节,你应该阅读jdk中的源代码.

      【讨论】:

      • 如果我重写了 DerivedMain 类中的 hashcode 方法,为什么永远不会被调用?
      • 您将Integers 作为您的地图中的键。所以Integer#hashcode() 会被调用。你没有覆盖它(你也不能)。您可以将 DerivedMain 实例放入映射中,然后使用您的哈希码(但您还需要提供 equals)。
      • 好的...谢谢现在我正在更改我在主类中的实现,其中插入创建整数作为键现在我将创建为:- DerivedMain d = new DerivedMain(); m.put(d, i);现在我的 hashmap 容量为 64。为什么?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多