Java HashMap行为不符合O(1)标记

时间:2013-07-07 10:09:14

标签: java hashmap

当我运行此程序时

public class MyHashMapOperationsDebug {

    public static void main(String[] args) {
        MyHashMap hashMap = new MyHashMap();//MyHashMap is replica of HashMap
        for (int i=1;i<=11;i++)
        hashMap.put(i, i+100);
        }
}

MyHashMap.java

void addEntry(int hash, K key, V value, int bucketIndex) {  //replica of HashMap's addEntry method  

Entry<K,V> e = table[bucketIndex];
**System.out.println("bucketIndex : " + bucketIndex);**
    table[bucketIndex] = new Entry<K,V>(hash, key, value, e);
    if (size++ >= threshold)
        resize(2 * table.length);
}

输出:

bucketIndex : 7  
bucketIndex : 14  
bucketIndex : 4  
bucketIndex : 13  
bucketIndex : 1  
bucketIndex : 8  
bucketIndex : 2  
bucketIndex : 11  
bucketIndex : 11  
bucketIndex : 2  
bucketIndex : 8  

为什么某些键会转到同一个桶,即使只有11个键存储在16号的地图中?例如。在索引2处有一个桶,而11每个都有两个键

修改 阅读下面的输入后面有一个问题:HashMap&amp; amp;使用Java的整数。是O(1)?

4 个答案:

答案 0 :(得分:13)

因为在不事先知道所有密钥的情况下,设计一种能够保证它们均匀分布的算法是不可能的。即使提前知道了所有密钥,如果其中两个具有相同的hashCode,它们也将始终位于同一个桶中。

这并不意味着HashMap不是O(1)。即使假设每个桶都有2个条目,无论映射中的条目数是多少,仍然会使每个get操作及时执行,而不依赖于映射中的条目数,这是O的定义(1 )。

答案 1 :(得分:1)

  

HashMap&amp; amp;使用Java的整数。是O(1)?

是。 Integer.hashcode()方法返回Integer本身的值,并且将在可能的哈希值空间内均匀分布。

因此哈希表的性能将是最佳的;即O(1)次操作getO(1)次操作的put(摊销)。由于可能只有2 ^ 32个唯一键,因此我们无需考虑HashMap如何扩展到该点之外的问题。

答案 2 :(得分:0)

E.g。在索引2处有一个桶,而11每个都有两个密钥:那是因为hashCollision。如果您对所有n个元素都有哈希冲突,HashMap可以在查找中提供O(n)的性能。这是哈希算法的糟糕设计。

事实上,你可以说,为了避免这些冲突,你需要分配一些额外的空间。因为你的哈希技术可以确保你没有多次碰撞,所以你显然需要额外的支持。

但与此同时,你不能完全避免碰撞,因为如果你的散列技术是每个桶只有一个条目,你将需要大量的空间。所以,实际上hashCollisions,在一个极限中是有好处的。

答案 3 :(得分:0)

预先知道密钥分布以设计o(1)散列函数是非常困难的。即使您知道密钥分发,您的密钥也可能映射到相同的插槽。因此,一旦您的负载系数移动到某个分数,您就需要进行重新运算。如果假设您的地图大小为16并且您有17个密钥,那么它将发生冲突。所以在这种情况下你需要有一些机制来重新映射地图以消除潜在的碰撞。

hashmap中的find操作渐近O(1)但它也可以转到o(n)。