Java--集合--Hashtable
- Hashtable基本介绍
- Hashtable 源码解析
- 执行 new Hashtable()
-
public Hashtable() { this(11, 0.75f); }
//默认的调用有参构造函数,且数组成都为11,加载因子为0.75 -
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;//创建一个长度为11的Entry类型的table数组
table = new Entry<?,?>[initialCapacity];
//获取临界值 threshold = (int)Math.min(initialCapacity * loadFactor, MAX_ARRAY_SIZE + 1); }
-
-
执行put方法
-
public synchronized V put(K key, V value) { // Make sure the value is not null
//如果value==null抛出空指针异常
if (value == null) { throw new NullPointerException(); } // Makes sure the key is not already in the hashtable.
//创建一个tab数组指向,table Entry<?,?> tab[] = table;
//计算出key的hash值 int hash = key.hashCode();
//key计算出的索引 int index = (hash & 0x7FFFFFFF) % tab.length; @SuppressWarnings("unchecked")
//拿到tab数组中下标为 index的节点entry Entry<K,V> entry = (Entry<K,V>)tab[index];
//循环遍历,下标为index的链表中是否存在和 要插入的元素一样的,如果有就将原来的value进行替换 for(; entry != null ; entry = entry.next) { if ((entry.hash == hash) && entry.key.equals(key)) { V old = entry.value; entry.value = value; return old; } } //如果遍历完了整个链表都没有和key相等的元素,就调用addentry()方法,将他加入到链表中 addEntry(hash, key, value, index); return null; } -
private void addEntry(int hash, K key, V value, int index) { modCount++; //操作数加一 //创建的tab数组 Entry<?,?> tab[] = table;
//判断如果节点数超过临界值就进行 rehash()方法进行扩容,操作,因为操作数的增加时在末尾,所以第八的元素添加时不会进行扩容,之后第九个元素进来的时候才会进行扩容操作if (count >= threshold) { // Rehash the table if the threshold is exceeded rehash(); tab = table; hash = key.hashCode(); index = (hash & 0x7FFFFFFF) % tab.length; } //没有超过临界值,就将元素加入到 tab[index]上 // Creates the new entry. @SuppressWarnings("unchecked") Entry<K,V> e = (Entry<K,V>) tab[index]; tab[index] = new Entry<>(hash, key, value, e); count++; }
-
protected void rehash() {
//得到旧表的长度 int oldCapacity = table.length;
//新建一个表指向旧表 Entry<?,?>[] oldMap = table; // overflow-conscious code
//信表长度等于旧表长度*2+1
int newCapacity = (oldCapacity << 1) + 1; if (newCapacity - MAX_ARRAY_SIZE > 0) { if (oldCapacity == MAX_ARRAY_SIZE) // Keep running with MAX_ARRAY_SIZE buckets return; newCapacity = MAX_ARRAY_SIZE; }
//新建一个长度为 newCapacity的新表 Entry<?,?>[] newMap = new Entry<?,?>[newCapacity]; //被修改的次数 modCount++;
//新的临界值 threshold = (int)Math.min(newCapacity * loadFactor, MAX_ARRAY_SIZE + 1);
//将表table执行新建的表 table = newMap; //将旧表中的数据复制到新表中 for (int i = oldCapacity ; i-- > 0 ;) { for (Entry<K,V> old = (Entry<K,V>)oldMap[i] ; old != null ; ) { Entry<K,V> e = old; old = old.next; int index = (e.hash & 0x7FFFFFFF) % newCapacity; e.next = (Entry<K,V>)newMap[index]; newMap[index] = e; } } }
-
- 执行 new Hashtable()
-
源码底说明
-
底层数组Hashtable$Entry[]初始化大小是11
-
临界值时 0.75,临界值时0.75*11=8
- 扩容机制:大于八的时候就会发生扩容,扩容为原来的一倍在加1:
int newCapacity = (oldCapacity << 1) + 1;
-
-
Hashtable和HashMap的对比
-