Map 接口实现类——HashTable

文章介绍了HashTable的基本概念,作为键值对存储的数据结构,它不允许键或值为null。HashTable是线程安全的,适合多线程环境,而HashMap则不是。文章详细讲解了HashTable的扩容机制,当元素数量超过临界值(默认为容量的75%)时,会通过rehash()方法进行扩容,新容量为旧容量的两倍加一。在扩容过程中,旧数组的元素被重新计算下标并插入新数组,以减少Hash碰撞并优化分布。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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+1
        int newCapacity = (oldCapacity << 1) + 1;
        // 保证新数组的大小永远小于等于MAX_ARRAY_SIZE
        // MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8
        if (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;
            }
        }
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值