> 文章列表 > Map 接口实现类——HashTable

Map 接口实现类——HashTable

Map 接口实现类——HashTable

HashTable基本介绍

  1. 存放的元素是键值对:即 K-V。
  2. HashTable 的键和值都不能为null,否则会抛出NullPointerException。
  3. HashTable 使用方法基本上和HashMap 一样。
  4. HashTable 是线程安全的(synchronized),HashMap是线程不安全的。

HashTable应用案例

  public static void main(String[] args) {Hashtable hashtable = new Hashtable();hashtable.put("jo",10); //添加成功//hashtable.put(null,10);//抛出异常//hashtable.put("jo",null);//抛出异常hashtable.put("lx",10);//添加成功hashtable.put("qw",10);//添加成功hashtable.put("qw",18);//value 替换System.out.println("hashtable= " + hashtable);}

输出:hashtable= {jo=10, qw=18, lx=10}

 HashTable底层说明

  1. 底层有数组 Hashtable$Entry[ ] ,初始化大小为11
  2. 临界值 threshold:8 = 11 * 0.75 (负载因子)
  3. 扩容:Hashtable的扩容机制通过rehash()来实现,如果Hashtable中元素的个数大于临界值时,会调用rehash()来实现扩容。临界值的大小等于Hashtable数组的大小与负载因子相乘,默认的负载因子大小为0.75。Hashtable扩容的数组长度是旧数组长度乘以2加1
  4. 执行方法 addEntry(int hash, K key, V value, int index);添加 K-V 封装到Entry。
  5. 当 if (count >= threshold) 添加元素个数大于等于临界值时,进行扩容。
  6. 按照 int newCapacity = (oldCapacity << 1) + 1; 进行扩容。
  7. Hashtable采用取模的方式来计算数组下标,同时数组的长度尽量为素数或者奇数,这样的目的是为了减少Hash碰撞,计算出来的数组下标更加分散,让元素均匀的分布在数组各个位置。 采用模运算,效率会比HashMap利用位运算计算数组下标更低。

rehash() 方法源码

protected void rehash() {int oldCapacity = table.length;Entry<?,?>[] oldMap = table;// 新数组的容量=旧数组长度*2+1int newCapacity = (oldCapacity << 1) + 1;// 保证新数组的大小永远小于等于MAX_ARRAY_SIZE// MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8if (newCapacity - MAX_ARRAY_SIZE > 0) {if (oldCapacity == MAX_ARRAY_SIZE)return;newCapacity = MAX_ARRAY_SIZE;}// 创建新数组Entry<?,?>[] newMap = new Entry<?,?>[newCapacity];modCount++;// 计算新的临界值threshold = (int)Math.min(newCapacity * loadFactor, MAX_ARRAY_SIZE + 1);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;}}}