Java Hashtable 源码(JDK8)

记录了HashMap也来看看Hashtable吧,最近打算换份实习,所以想看看书回顾一下,不然就快记不得了.....囧啊囧啊,记性太差怎么破???

Hashtable里面的一些变量:

Entry<?,?>[] table : HashTable采用"拉链法"实现哈希表,每一个Entry代表了一个键值对(key-value)。

transient int count:hashtable里面键值对的个数;

private int threshold:hashtable的阀值(threshols = capacity * loadFactor);

float loadFactor:加载因子;

transient int modCount :hashtable被修改的次数,用来实现fast-fail机制。fast-fail机制就是在并发集合中,其进行迭代操作时,若有其他线程对其进行结构性的修改,这时迭代器会立马感知到,并且立即抛出              ConcurrentModificationException异常。

Hashtable的定义如下:

1 public class Hashtable<K,V>
2     extends Dictionary<K,V>
3     implements Map<K,V>, Cloneable, java.io.Serializable {
4     ...
5 }

可以看出Hashtable实现了Map接口,同时继承了Dictionary类。Map接口是将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。Dictionary 类是任何可将键映射到相应值的类(如 Hashtable)的抽象父类。每个键和每个值都是一个对象。在任何一个 Dictionary 对象中,每个键至多与一个值相关联。给定一个 Dictionary 和一个键,就可以查找所关联的元素。任何非 null 对象都可以用作键或值。

看看Hashtable常用的构造函数的实现:

默认的构造函数:容量为11,加载因子为0.75

1 public Hashtable() {
2         this(11, 0.75f);
3     }

用指定的初始容量和默认的加载因子构造:

1 public Hashtable(int initialCapacity) {
2         this(initialCapacity, 0.75f);
3     }

用指定的初始容量和指定的加载因子构造:

 1  public Hashtable(int initialCapacity, float loadFactor) {
 2              // 参数合法性验证
 3             if (initialCapacity < 0)
 4                 throw new IllegalArgumentException("Illegal Capacity: "+
 5                                                    initialCapacity);
 6             if (loadFactor <= 0 || Float.isNaN(loadFactor))
 7                 throw new IllegalArgumentException("Illegal Load: "+loadFactor);
 8
 9             if (initialCapacity==0)
10                 initialCapacity = 1;
11             this.loadFactor = loadFactor;
12             //用指定容量初始化table数组
13             table = new Entry<?,?>[initialCapacity];
14             //计算table的阀值
15             threshold = (int)Math.min(initialCapacity * loadFactor, MAX_ARRAY_SIZE + 1);
16         }

再来看看Put方法和get方法:

  首先是put方法,put方法的整个处理流程是:计算key的hash值,根据hash值获得key在table数组中的索引位置,然后迭代该key处的Entry链表(我们暂且理解为链表),若该链表中存在一个这个的key对象,那么就直接替换其value值即可,否则在将改key-value节点插入该index索引位置处。注意,hashtable是不允许null值的。

int index = (hash & 0x7FFFFFFF) % tab.length——>键的hash值可能为负数,通过一个“与”操作,先将hash值都转化正数,然后将得到的hash值与Hashtable的长度求余

 1  //同步实现
 2      public synchronized V put(K key, V value) {
 3             // check value值是否为null
 4             if (value == null) {
 5                 throw new NullPointerException();
 6             }
 7
 8             // Makes sure the key is not already in the hashtable.
 9             Entry<?,?> tab[] = table;
10             //计算key的hash值
11             int hash = key.hashCode();
12             //通过hash值来计算在table数组中的下表
13             int index = (hash & 0x7FFFFFFF) % tab.length;
14             @SuppressWarnings("unchecked")
15             Entry<K,V> entry = (Entry<K,V>)tab[index];
16             //遍历,寻找该key,找到则替换旧值
17             for(; entry != null ; entry = entry.next) {
18                 if ((entry.hash == hash) && entry.key.equals(key)) {
19                     V old = entry.value;
20                     entry.value = value;
21                     return old;
22                 }
23             }
24             //没有找到,则将该key加入
25             addEntry(hash, key, value, index);
26             return null;
27         }
28          private void addEntry(int hash, K key, V value, int index) {
29                  //修改链表,modCount自增
30                 modCount++;
31
32                 Entry<?,?> tab[] = table;
33                 if (count >= threshold) {
34                     // Rehash the table if the threshold is exceeded
35                     rehash();
36                     tab = table;
37                     hash = key.hashCode();
38                     index = (hash & 0x7FFFFFFF) % tab.length;
39                 }
40
41                 // Creates the new entry.
42                 @SuppressWarnings("unchecked")
43                 Entry<K,V> e = (Entry<K,V>) tab[index];
44                 tab[index] = new Entry<>(hash, key, value, e);
45                 count++;
46         }

get方法也是同步的,具体的实现如下:

 1  public synchronized V get(Object key) {
 2             Entry<?,?> tab[] = table;
 3             //计算key的hash值
 4             int hash = key.hashCode();
 5             //通过hash值来计算在table数组中的下表
 6             int index = (hash & 0x7FFFFFFF) % tab.length;
 7             //遍历查找key,找到则返回key值所对应的的value
 8             for (Entry<?,?> e = tab[index] ; e != null ; e = e.next) {
 9                 if ((e.hash == hash) && e.key.equals(key)) {
10                     return (V)e.value;
11                 }
12             }
13             return null;
14         }
时间: 2024-11-06 03:51:43

Java Hashtable 源码(JDK8)的相关文章

转:【Java集合源码剖析】Hashtable源码剖析

转载请注明出处:http://blog.csdn.net/ns_code/article/details/36191279 Hashtable简介 Hashtable同样是基于哈希表实现的,同样每个元素是一个key-value对,其内部也是通过单链表解决冲突问题,容量不足(超过了阀值)时,同样会自动增长. Hashtable也是JDK1.0引入的类,是线程安全的,能用于多线程环境中. Hashtable同样实现了Serializable接口,它支持序列化,实现了Cloneable接口,能被克隆.

【Java集合源码剖析】Hashtable源码剖析

Hashtable简介 Hashtable同样是基于哈希表实现的,同样每个元素是一个key-value对,其内部也是通过单链表解决冲突问题,容量不足(超过了阀值)时,同样会自动增长. Hashtable也是JDK1.0引入的类,是线程安全的,能用于多线程环境中. Hashtable同样实现了Serializable接口,它支持序列化,实现了Cloneable接口,能被克隆. HashTable源码剖析 Hashtable的源码的很多实现都与HashMap差不多,源码如下(加入了比较详细的注释):

JAVA的HashTable源码分析

Hashtable简介 Hashtable同样是基于哈希表实现的,同样 每个元素是一个key-value对,其内部也是通过单链表解决冲突问题,容量不足(超过了阀值)时,同样会自动增长. Hashtable也是JDK1.0引入的类,是线程安全的,能用于多线程环境中. Hashtable同样 实现了Serializable接口,它支持序列化,实现了Cloneable接口,能被克隆 . HashTable源码剖析 Hashtable的源码的很多实现都与HashMap差不多,源码如下(加入了比较详细的注

Java 集合Hashtable源码深入解析

概要 前面,我们已经系统的对List进行了学习.接下来,我们先学习Map,然后再学习Set:因为Set的实现类都是基于Map来实现的(如,HashSet是通过HashMap实现的,TreeSet是通过TreeMap实现的). 首先,我们看看Map架构.如上图:(01) Map 是映射接口,Map中存储的内容是键值对(key-value).(02) AbstractMap 是继承于Map的抽象类,它实现了Map中的大部分API.其它Map的实现类可以通过继承AbstractMap来减少重复编码.(

Java入门系列之集合Hashtable源码分析(十一)

前言 上一节我们实现了散列算法并对冲突解决我们使用了开放地址法和链地址法两种方式,本节我们来详细分析源码,看看源码中对于冲突是使用的哪一种方式以及对比我们所实现的,有哪些可以进行改造的地方. Hashtable源码分析 我们通过在控制台中实例化Hashtable并添加键值对实例代码来分析背后究竟做了哪些操作,如下: public static void main(String[] args) { Hashtable hashtable = new Hashtable(); hashtable.p

java HashMap源码分析(JDK8)

这两天在复习JAVA的知识点,想更深层次的了解一下JAVA,所以就看了看JAVA的源码,把自己的分析写在这里,也当做是笔记吧,方便记忆.写的不对的地方也请大家多多指教. JDK1.6中HashMap采用的是位桶+链表的方式,即我们常说的散列链表的方式,而JDK1.8中采用的是位桶+链表/红黑树的方式,也是非线程安全的.当某个位桶的链表的长度达到某个阀值的时候,这个链表就将转换成红黑树. 基本的数据结构: 1 //链表节点 2 static class Node<K,V> implements

【Java集合源码剖析】HashMap源码剖析

转载请注明出处:http://blog.csdn.net/ns_code/article/details/36034955 HashMap简介 HashMap是基于哈希表实现的,每一个元素是一个key-value对,其内部通过单链表解决冲突问题,容量不足(超过了阀值)时,同样会自动增长. HashMap是非线程安全的,只是用于单线程环境下,多线程环境下可以采用concurrent并发包下的concurrentHashMap. HashMap 实现了Serializable接口,因此它支持序列化,

【转】Java HashMap 源码解析(好文章)

- .fluid-width-video-wrapper { width: 100%; position: relative; padding: 0; } .fluid-width-video-wrapper iframe, .fluid-width-video-wrapper object, .fluid-width-video-wrapper embed { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } [

Hashtable源码剖析

Hashtable简介 Hashtable同样是基于哈希表实现的,同样每个元素是一个key-value对,其内部也是通过单链表解决冲突问题,容量不足(超过了阀值)时,同样会自动增长. Hashtable也是JDK1.0引入的类,是线程安全的,能用于多线程环境中. Hashtable同样实现了Serializable接口,它支持序列化,实现了Cloneable接口,能被克隆. HashTable源码剖析 Hashtable的源码的很多实现都与HashMap差不多,源码如下(加入了比较详细的注释):