我知道在将键存储到内存地址时会应用哈希技术。
但我不明白碰撞是如何发生的?Java使用哪种哈希算法来创建内存空间?是MD5吗?
HashMap
的基本思想如下:
HashMap
实际上是一个特殊对象的数组,该数组同时保存键和值。hashCode()
方法提供。因此,在编写新的 Class
时,您应注意适当的 hashCode()
和 equals()
方法的实现。默认情况下(Object
类的方法),它将内存指针作为数字。但对于我们大多数想使用的类来说,这并不好。例如,String
类使用一种从字符串中所有字符生成哈希的算法 - 可以这样理解:hashCode = 1.char + 2.char + 3.char...
(简化)。因此,即使两个相等的字符串位于内存中的不同位置,它们也具有相同的 hashCode()
。hashCode()
的结果,比如 "132",就是如果我们有一个那么大的数组,对象应该存储在哪个桶中的编号。但我们没有,我们的数组只有16个桶。因此,我们使用明显的计算 'hashcode % array.length = bucket'
或 '132 mod 16 = 4'
并将键值对存储在桶编号为4的位置。HashMap
上最昂贵的操作,因此如果您知道要使用多少个桶,您需要告诉您的Map
。在这个例子中,
mod 256
处理之后,指向数组中的四个不同位置。现在,如果你尝试查找Sandra Dee的电话号码,你会对她的名字进行哈希运算并对256取模,然后查看桶152。在那里,你会找到John Smith。这不是Sandra,继续查找...啊哈,在John之后链接了Sandra。
Object
类中的 hashCode()
函数返回内存地址,用作 HashTable
和 HashMap
中作为键的哈希值。该函数与 IT 相关。String
类有它自己的hashCode()
实现,它不是使用内存位置,而是使用算法从字符串中的实际字符生成哈希值。 - Petr Janeček阅读完@Slanec的答案后,一定要查看Java-8的javadoc,因为有重大变化。例如:'TREEIFY',当每个桶(目前为8)中的条目数量达到阈值时,LinkedList将转换为TreeMap。
HashMap
和 HashTable
的,而不是关于 TreeMap
的,因为 TreeMap
根本不使用哈希。 - user207421TreeMap
类似(具有明显和不明显的差异,例如非可比较键按其 hashCode()
排序),碰撞的键会被重组成树形结构,而不是一个单链表。这有助于防止许多碰撞的灾难性情况,在这种情况下,Java 8 之前的 HashMap
会缓慢地退化为一个链接列表。 - Petr Janeček
String
的真正hashCode()
实现。还有一些关于hashCode()
中素数选择的链接,包括一些随机链接。 - Petr JanečekHashMap
实际上所做的。首先,它将hashCode()
的高16位和低16位进行异或运算。HashTable
也不是这样做的。 - user207421HashMap
非常快。但显然,这个答案并不包含它们,以免混淆OP。我相信他当时是个新手,需要了解算法基础,而不是低级优化。 - Petr Janeček