史上最详细的Hashtable详解--源码分析
2016-03-29 10:36
393 查看
ps.本文所有源码都是基于jdk1.6
图1-1
1.继承不同
HashMap继承AbstractMap而Hashtable继承Dictionary,现在Dictionary已经被Map取代了,所以有人说继承不同完全是因为历史原因
2.初始容量不同
//HashMap
HashMap的容量必须是2的幂次方,这个也是有原因的,因为HashMap取table下标的时候,是用h & (length -1 ) 实现的,来保证结果小于等于length -1 ,这个详细介绍在HashMap文章有介绍。为什么HashMap用这种方式实现呢,因为位屏蔽要比整数除法快。
//Hashtable
Hashtable 的容量增加逻辑是乘2+1,保证奇数。
在应用数据分布在等差数据集合(如偶数)上时,如果公差与桶容量有公约数n,则至少有(n-1)/n数量的桶是利用不到的。
实际上 HashMap 也会有此问题,并且不能指定桶容量。所以 HashMap 会在取模哈希前先做一次哈希
3.HashMap接受key和value为null的情况,Hashtable不接受
4.HashMap是线程不同步的,Hashtable是线程同步的
5.扩容策略不同,HashMap扩容2倍,Hashtable扩容2倍+1(为了保证奇数)
Hashtable数据结构
Hashtable和HashMap的数据结构是一样的,都是一个数组和链表的结合体,如图1-1所示。private transient Entry[] table; private transient int count; private static class Entry<K,V> implements Map.Entry<K,V> { int hash; K key; V value; Entry<K,V> next; ... }
图1-1
Hashtable和HashMap的区别
因为Hashtable和HashMap太相似了,所以就不单独介绍Hashtable了,感兴趣的可以先去前面的文章看一下HashMap,再回过头来看这个。1.继承不同
/** HashMap */ public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable /** Hashtable */ public class Hashtable<K,V> extends Dictionary<K,V>implements Map<K,V>, Cloneable, java.io.Serializable
HashMap继承AbstractMap而Hashtable继承Dictionary,现在Dictionary已经被Map取代了,所以有人说继承不同完全是因为历史原因
2.初始容量不同
/** HashMap */ static final int DEFAULT_INITIAL_CAPACITY = 16; static final float DEFAULT_LOAD_FACTOR = 0.75f; /** Hashtable */ public Hashtable() { this(11, 0.75f); }
//HashMap
HashMap的容量必须是2的幂次方,这个也是有原因的,因为HashMap取table下标的时候,是用h & (length -1 ) 实现的,来保证结果小于等于length -1 ,这个详细介绍在HashMap文章有介绍。为什么HashMap用这种方式实现呢,因为位屏蔽要比整数除法快。
//Hashtable
Hashtable 的容量增加逻辑是乘2+1,保证奇数。
在应用数据分布在等差数据集合(如偶数)上时,如果公差与桶容量有公约数n,则至少有(n-1)/n数量的桶是利用不到的。
实际上 HashMap 也会有此问题,并且不能指定桶容量。所以 HashMap 会在取模哈希前先做一次哈希
3.HashMap接受key和value为null的情况,Hashtable不接受
4.HashMap是线程不同步的,Hashtable是线程同步的
5.扩容策略不同,HashMap扩容2倍,Hashtable扩容2倍+1(为了保证奇数)
/** HashMap */ resize(2 * table.length); /** Hashtable */ protected void rehash() { ... int newCapacity = oldCapacity * 2 + 1; Entry[] newMap = new Entry[newCapacity]; ... }
相关文章推荐
- u-boot源码分析第一阶段之Start.S
- Android 快速开发系列 打造万能的ListView GridView 适配器
- Java中如何获取系统信息
- 搭建树莓派交叉编译环境
- iOS开发-beginUpdates && endUpdates用法
- 个人对B/S项目的一些理解(一)
- SimpleDateFormat 相关用法
- 一个开发眼中的运维
- 修改mysql全日志中一个sql多行的perl脚本
- JSP的八个内置对象
- 第十二章 图形用户接口
- 在ThinkPHP3.2中使用memcache
- 系统的分享。
- 3月第3周网络安全报告:被篡改.COM网站占74.3%
- 宏的应用
- ConcurrentHashMap和HashMap的区别
- UIScrollViewDelegate
- js 字符串转换数字
- #每日一题#腾讯笔试题
- kernel 增加自定义宏编译开关