HashMap 实现原理。
自带的变量:
initialCapacity:初始容量。HashMap集合初始化时自身的容量。可以在构造方法中指定。默认容量是16,指定大小是,必须是2的幂次方。
size:当前 HashMap 中已经存储着的键值对数量,即 HashMap.size()
loadFactor:加载因子,就是当HashMap容量达到一定值时,HashMap会执行扩容,可以在构造方法中指定,默认是0.75。例如,一个HashMap的初始容量为16,那么扩容的阈值为0.75*16=12。也就是说当存入第13个值的时候,HashMap会先执行扩容。
threshold,扩容阈值,扩容阈值=容量*加载因子。
table,Entry数组。HashMap内部存储key/value是通过Entry这个介质来实现的。而table就是Entry数组。Entry<K,V> [] table
在Java1.7中,HashMap的实现方法是数组+链表的形式。而数组中的每个元素,都是链表的第一个结点。即如下图所示:
Java 1.8 中 HashMap 的不同
1. 在 Java 1.8 中,如果链表的长度超过了 8 ,那么链表将转化为红黑树;
2. 发生 hash 碰撞时,Java 1.7 会在链表头部插入,而 Java 1.8 会在链表尾部插入;
3. 在 Java 1.8 中,Entry 被 Node 代替(换了一个马甲)
简单来说,HashMap是由数组+链表组成的,数组才是HashMap的主体,链表则是为了解决哈希冲突而存在的,如果定位到的数组位置不含链表(当前entry的next指向null),那么对于查找、添加等才做很快,仅需一次寻址即可;如果定位到的数组包含链表,对于添加操作,其时间复杂度为O(n)(首先遍历链表,存在即覆盖,否则新增)。对于查找操作来讲,仍需遍历链表,然后通过key对象的equals方式逐一比对查找。所以,考虑到性能,HashMap的链表越少,性能才会越好。
Hashtable实现原理:
- Hashtable的默认容量是11,默认负载因子为0.75.
- Hashtable的容量可以为任何整数,最小值为1。
- 为了避免扩容带来的性能问题,指定合理容量。
- threshold扩容阈值:容量*负载因子。当hashtable的键值对数量大于这个阈值时,就进行扩容。newCapacity = oldCapaciaty * 2 + 1.
- 当Hashtable添加键值对时,首先对key判断(1、先获取key的hashcode key.hashcode();;2、计算器索引index=(hashcode&0x7FFFFFFF)%(当前entry数组的长度)).获取当前entry数组对应该entry[index],如果key相等则直接覆盖,如果key值不相等则添加entry<>[index].add(key,value);