HashTable学习笔记
1、Hashtable简单介绍
HashTable是线程安全的数据结构,多个线程可以共享一个HashTable
HashTable的Key和Value都不允许为null
HashTable底层用数组和链表进行实现
HashTable默认容量为11,负载因子为0.75
HashTable每次扩容大小为 *2+1
HashTable的遍历通过Enumeration
HashMap是通过”拉链法”实现的哈希表。它包括几个重要的成员变量: table, size, threshold, loadFactor, modCount。
①table是一个Entry[]数组类型,而Entry实际上就是一个单向链表。哈希表的”key-value键值对”都是存储在Entry数组中的。
②size是HashMap的大小,它是HashMap保存的键值对的数量。
③threshold是HashMap的阈值,用于判断是否需要调整HashMap的容量。threshold的值=“容量*负载因子”,当HashMap中存储数据的数量达到threshold时,就需要将HashMap的容量加倍。
④loadFactor就是负载因子。
⑤modCount是用来实现fail-fast机制的。
2、HashTable的四种构造函数
1、public Hashtable(int initialCapacity, float loadFactor)
public Hashtable(int initialCapacity, float loadFactor) {if (initialCapacity < 0)throw new IllegalArgumentException("Illegal Capacity: "+initialCapacity);if (loadFactor <= 0 || Float.isNaN(loadFactor))throw new IllegalArgumentException("Illegal Load: "+loadFactor);if (initialCapacity==0)initialCapacity = 1;this.loadFactor = loadFactor;table = new Entry<?,?>[initialCapacity];threshold = (int)Math.min(initialCapacity * loadFactor, MAX_ARRAY_SIZE + 1);}
指定初始容量,和负载因子
2、public Hashtable(int initialCapacity)
public Hashtable(int initialCapacity) {this(initialCapacity, 0.75f);}
指定初始化容量,使用默认的负载因子0.75
3、public Hashtable()
public Hashtable() {this(11, 0.75f);}
无参构造函数,使用默认容量11和默认的初始化影子0.75
4、public Hashtable(Map<? extends K, ? extends V> t)
public Hashtable(Map<? extends K, ? extends V> t) {this(Math.max(2*t.size(), 11), 0.75f);putAll(t);}
创造一个包含Map的子类
3、HashTable的原理
简单来说,HashTable的原理和HashMap是一样的,HashMap是HashTable的轻量级实现
有关原理部分可以看我有关HashMap的笔记HashMap的学习笔记
4、HashTable几个方法详解
1、get方法
public synchronized V get(Object key) {Entry<?,?> tab[] = table;int hash = key.hashCode();int index = (hash & 0x7FFFFFFF) % tab.length;for (Entry<?,?> e = tab[index] ; e != null ; e = e.next) {if ((e.hash == hash) && e.key.equals(key)) {return (V)e.value;}}return null;}
①HashTable的get方法是同步的,因为它加了锁
②我们可以看到它求数组下表的方式是(hash & 0x7FFFFFFF) % tab.length
0x7FFFFFFF是一个质数,这样可以保证(hash & 0x7FFFFFFF)进行于运算后出来一个正整数,不会产生数组下表的异常
③当找到数组下表后,就是常见的循环链表判断操作,直到找出这个数
2、put
public synchronized V put(K key, V value) {// Make sure the value is not nullif (value == null) {throw new NullPointerException();}// Makes sure the key is not already in the hashtable.Entry<?,?> tab[] = table;int hash = key.hashCode();int index = (hash & 0x7FFFFFFF) % tab.length;@SuppressWarnings("unchecked")Entry<K,V> entry = (Entry<K,V>)tab[index];for(; entry != null ; entry = entry.next) {if ((entry.hash == hash) && entry.key.equals(key)) {V old = entry.value;entry.value = value;return old;}}addEntry(hash, key, value, index);return null;}
put方法也非常容易理解,主要就是判断了Key和Value不允许为空,然后同样使用拉链法
先计算hash确定位置,然后使用链表
