术语
- 散列表(哈希表)
散列表英文就是Hash Table,也就是我们经常说的哈希表,散列表用的是数组支持按照下标随机访问数据的特性,所以散列表其实就是数组的一种扩展,由数组演化而来.可以说,如果没有数组,就没有散列表。
- 散列函数
对N取模x=x,其实这就是一个散列函数。也就是大家经常看到的Hash(key),这个Hash函数就是我们说的散列函数。我们是通过它来计算散列的值的。
- hashCode
java里面调用hashCode()方法其实给我们返回的就是一个jvm堆里面存储该对象数据的一个虚拟地址(哈希值),不同虚拟机实现可能不同
Hash碰撞
就是经过hash函数处理后得到的值一样
解决方法
1.开放寻址(线性探测)
- 插入
20%10=0,发现0已经有数据了则向下探测,直到没有数据的空位置则插入
- 查找
查找20的时候就是20%10=0,发现0不是想要的20数据,继续线性探测,但会出现问题,假如删除了1的数据,它线性探测发现1空了,就会返回null,找不到,其实是有的,这时候我们可以加一个delete标记位,找的时候就继续往下找
2.链路地址(使用链表)
优点,使用简单,插入和删除容易(修改指针即可)
缺点:遍历慢
针对链表缺点遍历慢的问题,我们可以使用高级数据结构二叉查找树去解决
HashMap(JDK1.8)
- 优点:速度快
- 缺点:线程不安全,存不了大数据
初始大小: HashMap默认的初始大小是16,这个默认值是可以设置的,如果事先知道大概的数据量有多大,可以通过修改默认初始大小,减少动态扩容的次数,这样会大大提高HashMap的性能。
动态扩容:最大装载因子默认是0.75,当HashMap中元素个数超过0.75*capacity (capacity表示散列表的容量)的时候,就会启动扩容,每次扩容都会扩容为原来的两倍大小。
Hash冲突解决办法:JDK1.7底层采用链表法。在JDK1.8版本中,为了对HashMap做进一步优化,我们引入了红黑树。而当链表长度太长(默认超过8)时,链表就转换为红黑树。我们可以利用红黑树快速增删改查的特点,提高HashMap的性能。当红黑树结点个数少于8个的时候,又会将红黑树转化为链表。因为在数据量较小的情况下,红黑树要维护平衡,比起链表来,性能上的优势并不明显。
HashTable
- 优点:线程安全
- 缺点:影响性能