扩容:首次创建 HashMap,会指定其容量(如果未明确指定,默认是 16),后续不断的向 HashMap 中 put 元素,如果 元素个数(size)超过临界值(threshold) 的时候,就会进行自动扩容(resize),并且,在扩容之后,还需要对 HashMap 中原有元素进行 rehash,即将原来桶中的元素重新分配到新的桶中。
负载因子(loadFactor):
loadFactor 是装载因子(负载因子),表示 HashMap 满的程度,默认值为 0.75f,也就是说默认情况下,当 HashMap 中元素个数达到了容量的 3/4 的时候就会进行自动扩容。如果负载因子越大,对空间的利用更充分,但是查找效率会降低(链表长度会越来越长);如果负载因子太小,那么表中的数据将过于稀疏(很多空间还没用,就开始扩容了),对空间造成严重浪费。系统默认加载因子为0.75,这是一个比较理想的值,一般情况下我们是无需修改的。
另外,无论我们指定的容量为多少,构造方法都会将实际容量设为不小于指定容量的2的次方的一个数,且最大值不能超过2的30次方
临界值(threshold) = 负载因子(loadFactor) * 容量(capacity)。
1、继承的父类不同
Hashtable继承自Dictionary类,而HashMap继承自AbstractMap类。但二者都实现了Map接口。
2、HashMap是非线程安全的,Hashtable是线程安全的
HashMap:当我们进入put方法查看源码时可以发现put方法返回的方法只有个finla修饰,没有任何关于线程的存在
Hashtable:当我们点击进入之后,就能马上看到一个synchronized关键字(这个锁的是类实例的方法),表示同一个实例对象的这个方法在调用的时候不能被其他的线程对象访问。
3. HashMap允许null作为键或值,Hashtable不允许,运行时会报NullPointerException
从上面Hashtable的put方法,value值为null时,会抛出一个异常NullPointerException
给HashMap传入空值时,分别查看它们的size时,HashMap会得到一个1
hashMap会先判断key是不是为null
4. HashMap添加元素使用的是自定义hash算法,Hashtable使用的是key的hashCode
5. HsahMap在数组+链表的结构中引入了红黑树,Hashtable没有
hash结构它的底层数据结构存储应该是一个数组加列表的形式,所以HashMap和Hashtable它的底层存储机制都是数组加列表的结构,但是在jdk 1.8版本之后HashMap增加了一个新的结构叫做红黑树。
6. HashMap初始容量为16,Hashtable初始容量为1
7. HsahMap扩容是当前容量翻倍,Hashtable是当前容量翻倍+
8. HsahMap只支持Iterator遍历,Hashtable支持Iterator和Enumeration
遍历的机制HashMap有一个叫keyset还有一个叫Entryset的两个方法,得到的结果都是Iterator(迭代器)。
而Hashtable有一个叫elements的方法,他的结果是Enumeration,同时Hashtable也能得到key和Entry,所以Hashtable的遍历方式多了一个机制。
9. HsahMap与Hashtable的部分方法不同,比如Hashtable有contains方法。
Hashtable中有contains方法,HsahMap中就没有。HsahMap只有containsKey和containsValue但是没有contains。