以下是基于java1.8源码进行对比:
类型 | HashMap | Hashtable | ConcurrentHashMap |
---|---|---|---|
数据结构 | 数组+链表+红黑树 | 数组+链表 | 数组+链表+红黑树 |
数组容量 | 默认容量为16,且要求底层数组的容量一定为2的整数次幂 | 默认容量为11,且不要求底层数组的容量一定为2的整数次幂 | 默认容量为16,且要求底层数组的容量一定为2的整数次幂 |
是否支持NULL值 | 支持 | 不支持 | 不支持 |
size获取 | size字段值 | count字段值 | 通过累加baseCount和CounterCell数组中的数量,得到元素的总个数 |
hash计算方式 | key.hashCode() ^ (key.hashCode() >>> 16) | key.hashCode() | (key.hashCode() ^ (key.hashCode() >>> 16)) & 0x7fffffff |
index计算方式 | (n - 1) & hash | (hash & 0x7FFFFFFF) % tab.length | (hash & 0x7FFFFFFF) % tab.length |
是否线程安全 | 否 | 是 | 是 |
性能高低 | 高 | 低 | 中 |
线程安全实现方式 | 无 | synchronized对象锁,get、add、remove等方法不能同时进行 | CAS + synchronized保证多线程安全,可以同时执行多个方法 |
扩容方式 | 单线程进行扩容(多线程进行扩容,可能会导致死循环造成CPU100%) | 单线程进行扩容 | 单线程对新数组进行初始化,可多线程同步复制不同节点数据到新数组 |
HashTable是已过时的类,不建议再使用;总结:
- 需要线程安全的场景,使用ConcurrentHashMap;
- 无需线程安全,使用HashMap;