《Java源码分析》:Hashtable
来源:互联网 发布:淘宝的淘龄是怎么算的 编辑:程序博客网 时间:2024/06/05 17:30
Java源码分析》:Hashtable
Hashtable类的实现也是基于“数组和链表”来实现的。
Hashtable的继承关系为:
- 1
- 2
- 3
继承的是Dictionary类,实现了Map、Cloneable、Serializable。
注意:这也是Hashtable和HashMap第一个不同的地方,HashMap实现的是AbstractMap类。
1、Hashtable的几个属性
1)、private transient Entry<?,?>[] table;
//用来实现Hashtable所借助的数组,默认大小为11.
注意:这是Hashtable与HashMap第二个不同的地方,Hashtable的默认容量大小为11,HashMap的默认容量大小为16且扩容的大小必须一直是2的幂次方。
2)、private transient int count;
//用来记录table数组中存储元素的个数
3)、private int threshold;
//扩容的门限,即如果数组table中存储的元素个数大于threshold,则扩大数组table的大小
4)、private float loadFactor;
//加载因子,默认值为0.75f,扩容门线threshold的值等于loadFactor与数组table的容量的乘积.
2、Hashtable的构造函数
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
Hashtable几个常见的方法
1、put(K key, V value)
put方法存储数据的思想如下:首先根据拿到key的hashcode,然后根据hashCode找到此元素即将要存储的位置index.如果位置index已经有元素链表了,则在此链表中,寻找是否有key已经存在了,如果存在,则更新value值,如果不存在,则将此value存储在index位置上。
源码如下:
从源码中可以看到,put方法首先检查value是否为null,如果为空,则抛异常。
注意:这也是Hashtable与HashMap的另一个不同点,在HashMap中,null可以作为键,这样的键只有一个;可以有一个或多个键所对应的值为null。
另一个区别
在Hashtable中所有的方法都是用synchronized关键字进行了同步,而HashMap中的方法在缺省情况下是非同步的。在多线程并发的环境下,可以直接使用Hashtable,但是要使用HashMap的话就要自己增加同步处理了。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
在上面的put方法中在添加新节点时,调用了addEntry方法,下面就来看下这个方法的源码,看看这个方法是如何将一个节点添加到数组table中的。
2、addEntry(int hash, K key, V value, int index)
给数组table的index位置添加元素。
思想如下:首先检查下数组table存储的元素个数是否大于扩容门限threshold.如果大于,则扩容,扩容之后,重新获取key的hashcode,并根据hashcode重新计算要存储的位置index.最后将要存储的数据存储到table[index]中。这里要注意的一点是,如果table[index]中已经有其它元素了,那么在同一个位子上的元素将以链表的形式存放,新加入的放在链头,最先加入的放在链尾。
源码如下:(在代码中进行了一定的注释)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
由于addEntry方法里面有一个rehash方法,rehash方法是用来对数组table进行扩容的,下面我们来看看这个方法里面是如何来实现的。
3、rehash()
rehash方法的实现思想如下:首先对原来的长度乘以2+1就为即将扩容的长度。然后新建一个newCapacity的数组,将原来的table数组的元素拷贝到新的数组中去即可。
具体实现源码如下:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
4、内部类Entry
内部类Entry,都说Hashtable是数组和链表的结合体,而Entry就类似于起着链表的作用。
源码如下:(比较简单)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
5、get方法
上面说了put方法,我们也就不得不说下get方法了
get方法的思想也比较简单,如下:首先获取key的hashcode,然后根据hashcode得到存储位置index,最后在table[index]取出元素即可,不过要注意的是,这里可能存储了多个元素构成了一个链表,因此要进行一个key和hash的判断。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
以上基本就对Hashtable有了一个大致的了解,而类似于remove、contain方法都比较简单,这里不再进行介绍。
- Java-HashTable源码分析
- 《Java源码分析》:Hashtable
- 《Java源码分析》:Hashtable
- [Java] Hashtable 源码简要分析
- Java数据结构源码分析-HashTable
- 【Java源码分析】HashTable源码分析
- 【Java基础提高】HashTable源码分析(六)
- java的HashTable的部分源码分析
- Java基础——HashTable源码分析
- 【Java集合类源码分析】Hashtable源码分析
- HashTable & HashSet 源码分析
- Hashtable 源码分析
- HashTable源码分析
- Hashtable源码分析
- Hashtable源码分析
- STL hashtable 源码分析
- HashTable源码分析
- hashtable源码分析
- crawl spider的使用
- 面试总结
- 修改Jupyter Notebook的默认路径
- MATLAB 标定工具箱使用教程
- 程序员都应该懂一点开源协议
- 《Java源码分析》:Hashtable
- 分布式文件系统fastdfs
- 系统安全篇
- Android事件机制----KeyEvent
- linux / unix 网络性能测试工具iperf详细使用图文教程
- hql 中 exists 用法, and 异常 解决
- SpringBoot事务注解@Transactional
- 利用eclipse + qemu| Vmware + gdb 调试linux内核
- 《Java源码分析》:HashMap