Hashtable 从jdk1.0就有了,而HashMap是jdk1.2添加了,ConcurrentHashMap在jdk1.5才提供。
Hashtable和ConcurrentHashMap都是线程安全的。可是ConcurrentHashMap是1.5添加的更高级的并发工具。它使用了分段锁技术来实现更细粒度的同步。所以ConcurrentHashMap比Hashtable效率较高,所以在多线程状况下通常使用ConcurrentHashMap。而HashMap是非线程安全的,所以通常在单线程下使用。html
优先选择:多线程访问:ConcurrentHashMap。单线程访问:HashMapjava
写个简单易懂的代码做为例子,代码以下,而后分别在有注释的两行代码前设置断点:api
public class HashMapL { public static void main(String[] args) { HashMap<Integer, Integer> hashMap = new HashMap<>(); hashMap.put(null, null); //test null key and null value; for(int i=0; i<16; i++){ hashMap.put(i, i); //autoboxing } }
以debug模式运行上面代码能够看出HashMap<Integer, Integer> hashMap = new HashMap<>();初始化了以下的hashMap:
数组
从上图能够看到,负载因子loadfactor默认值是0.75。注意,threshold如今的值时0。根据HashMap源码里面的注释能够知道,这个值是在给table分配空间后才会计算threshold的值,分配前它的值是0,而如今table的值为null,还没有分配。那么这里的table是什么呢?了解拉链式哈希表的人就会轻易知道它是一个链表数组。安全
按F6执行下一步,给hashMap赋值,而且是空值,来验证与Hashtable的区别:能够保存空值。
多线程
从上图能够看到,并发
继续按F6,直到size=threshold=12,此刻table的id和以前的同样,仍是id=24
oracle
如今再按一次F6执行下一步,向hashMap里添加一个元素,让元素的总数size大于阈值threshold
工具
从图片中看到,table的id=104,大小为32,阈值threshold=24。而以前的id=24,大小为16,threshold=12。所以得出结论,性能
当元素大小size大于阈值threshold时就会进行再哈希。再哈希后,HashMap就会自动扩容为以前的2倍。而且用一个新的对象代替原来的对象。 由此也可得知,自动扩容是须要消耗资源的,要尽可能减小自动扩容的发生。
API文档
How HashMap works in java,强烈推荐! (以前看了这篇文章感受真的太好了,有种本身不用写了感受。因此这篇博文最主要的目的是总结下HashMap的特色。和这篇文章的debug思路)