哈希时不可避免的碰撞?

时间:2014-10-23 01:38:09

标签: java map hashmap

如果我创建新的Map

Map<Integer,String> map = new HashMap<Integer,String>();

然后我多次拨打map.put(),每个都有一个唯一的密钥,比如一百万次,是否会发生冲突,或者如果密钥是唯一的,那么java的哈希算法可以保证不会发生冲突?

3 个答案:

答案 0 :(得分:3)

如果密钥是唯一的,则散列不保证不会发生冲突。实际上,唯一需要的是相等的对象具有相同的哈希码。碰撞的数量决定了检索的有效性(更少的碰撞,更接近O(1),更多的碰撞,更接近O(n))。

对象的哈希码将取决于它的类型。例如,字符串的默认哈希码是

s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]

这必然会将字符串的复杂性简化为单个数字 - 绝对有可能使用两个不同的字符串来达到相同的哈希码,尽管它很少见。

如果两件事情都是哈希,那么hashmap使用.equals来确定特定的密钥是否匹配。这就是为什么同时重写hashCode()equals()以及确保相同的内容具有相同的哈希码的重要性。

答案 1 :(得分:1)

Hashtable的工作方式如下:

  1. 使用初始容量(或桶数)创建散列映射

  2. 每次向它添加一个对象时,java都会调用该键的哈希函数,一个数字,然后将其模数为哈希表的当前大小

  3. 对象存储在存储桶中,其结果来自步骤2.

  4. 因此,即使您拥有唯一的密钥,它们仍然会发生冲突,除非您的密钥范围与密钥的哈希范围一样多。

答案 2 :(得分:1)

您需要了解两件事:

  1. 即使有碰撞,也不会引起问题,因为对于每个桶,都有一个列表。如果你要放入一个已经有值的桶,它只会附加在列表中。检索时,它将首先找出要查找的存储桶,然后从存储桶中查看列表中的每个值并找出等于的值(通过调用equals()

  2. 如果你在Hashmap中投入数百万的价值,你可能会想,那么地图中的每个链表都会包含数千个值。然后我们总是进行大线性搜索,这将很慢。然后你需要知道,只要条目数大于某个阈值(看看容量和Javadoc中的loadFactor),就会调整Java的HashMap的大小。使用正确实现的哈希码,每个桶中的条目数量将会很小。