Map集合框架(四)——HashTable(JDK1.8)

(一)HashTable子父层级:

HashTable层级图
HashTable继承于抽象类Dictionary,主要是定义一些抽象方法,用于HashTable子类实现。

(二)Map实现类

1、HashTable实现类

1HashTable底层是Entry数组+链表,transient Entry<?,?>[] table;2HashTable默认容量为11或者构造方法指定初始容量,无参构造器中默认容量11和负载因子0.75f;3HashTable扩容是翻倍+1int newCapacity = (oldCapacity << 1) + 1;//(位运算:左移一位)4HashTable利用无参和有参构造方法可以指定负载因子,默认为110.75f;5HashTable重要成员变量:扩容阈值int threshold(默认11*0.75f)、负载因子float loadFactor(默认0.75,可设置),
    存储数组为Entry<?,?>[] table;6HashTable返回size方法中使用的count成员,HashMap的size方法返回的是size成员;7HashTable是线程安全的,因为其底层涉及到数据的方法均带有synchronized保证在多线程环境中数据安全,但因此性能也较低。

2、常见源码

(1)构造方法
//无参构造,使用默认容量11和默认负载因子0.75f
 public Hashtable() {
     this(11, 0.75f);
 }
 //带容量设置的含参构造方法,默认0.75f负载因子
 public Hashtable(int initialCapacity) {
     this(initialCapacity, 0.75f);
 }
 //基于map映射到新的集合
 public Hashtable(Map<? extends K, ? extends V> t) {
     this(Math.max(2*t.size(), 11), 0.75f);
     putAll(t);
 }
 //指定初始容量和负载因子
 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;//强行改变初始值为0的设置
     this.loadFactor = loadFactor;//设置负载因子
     table = new Entry<?,?>[initialCapacity];//对存储数组进行初始化
     threshold = (int)Math.min(initialCapacity * loadFactor, MAX_ARRAY_SIZE + 1);//计算阈值并转为整型
 }
(2)put方法
//涉及到数据,因此该方法有synchronized同步且K——V键值对都不允许为null
 public synchronized V put(K key, V value) {
     if (value == null) {//不允许值为null
         throw new NullPointerException();
     }
     Entry<?,?> tab[] = table;
     int hash = key.hashCode();//与hashMap区别很大,此处直接使用key的hashCode
     int index = (hash & 0x7FFFFFFF) % tab.length;//计算key在数组中的桶位置
     @SuppressWarnings("unchecked")
     Entry<K,V> entry = (Entry<K,V>)tab[index];
     for(; entry != null ; entry = entry.next) {//遍历该桶,是否已存在对应的key
         if ((entry.hash == hash) && entry.key.equals(key)) {
             V old = entry.value;//旧值
             entry.value = value;//设置新的值
             return old;//返回旧值
         }
     }
     //将新的键值对保存在数组中
     addEntry(hash, key, value, index);
     return null;
 }
 //键值对入数组或者链表
 private void addEntry(int hash, K key, V value, int index) {
     modCount++;
     Entry<?,?> tab[] = table;
     if (count >= threshold) {//是否扩容
         rehash();//扩容
         tab = table;
         hash = key.hashCode();
         index = (hash & 0x7FFFFFFF) % tab.length;//利用模运算进行取余进行确定桶位置
     }
     @SuppressWarnings("unchecked")
     Entry<K,V> e = (Entry<K,V>) tab[index];
     tab[index] = new Entry<>(hash, key, value, e);//赋值
     count++;//数量自增
 }
(3)rehash扩容方法
 protected void rehash() {
     int oldCapacity = table.length;
     Entry<?,?>[] oldMap = table;
     int newCapacity = (oldCapacity << 1) + 1;//扩容值即左移一位并+1
     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;//重新赋值给桶位置
         }
     }
 }
(4)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;//返回指定key对应的值
         }
     }
     return null;
 }
(5)remove方法
 public synchronized V remove(Object key) {
     Entry<?,?> tab[] = table;
     int hash = key.hashCode();
     int index = (hash & 0x7FFFFFFF) % tab.length;//确定桶位置
     @SuppressWarnings("unchecked")
     Entry<K,V> e = (Entry<K,V>)tab[index];
     for(Entry<K,V> prev = null ; e != null ; prev = e, e = e.next) {//遍历链表
         if ((e.hash == hash) && e.key.equals(key)) {
             modCount++;
             if (prev != null) {//删除节点前是否有Entry键值对
                 prev.next = e.next;//对键值对进行删除
             } else {
                 tab[index] = e.next;//删除节点为桶位置即直接将后续键值对提前
             }
             count--;
             V oldValue = e.value;
             e.value = null;
             return oldValue;//返回删除值
         }
     }
     return null;
 }

3、总结

1HashTable底层为Entry数组+链表,涉及数据的方法如put、remove、get等方法
    均有synchronized保证线程安全和同步即数据强一致性,相对来说性能将下降;2HashTable核心成员变量Entry<K,V> table,int count,阈值int threshold,负载因子float loadFactor等,
    无参和有参构造函数对容量和负载因子赋值,无参则默认110.75f,扩容则是当前容量翻倍并+1进行数组扩容;3HashTable获取size是由成员变量count变量获取,HashMap则是使用成员变量size获取,
    扩容机制不同即前者使用翻倍+1,后者使用翻倍,hash也不一样即前者直接使用key的hashcode,后者使用扰乱算法。
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
ConcurrentHashMap is a thread-safe implementation of Map interface that allows concurrent access to the map from multiple threads without any data inconsistency or race condition. It was introduced in Java 5 and has been improved in Java 6 and Java 7. Some of the key features of ConcurrentHashMap are: - It is highly concurrent and supports high throughput. - It allows multiple threads to read and write the map concurrently without any blocking. - It provides better performance than Hashtable and synchronizedMap. - It supports high concurrency level with a tunable concurrency level that can be set during initialization. - It provides various methods for bulk operations such as putAll, clear, and replaceAll. - It supports atomic operations such as putIfAbsent, remove, and replace. In JDK 1.8, ConcurrentHashMap has been further improved with the addition of new methods and enhancements such as: - forEach() method: This method allows you to iterate over the key-value pairs in the map and perform an action on each of them. - compute() and computeIfAbsent() methods: These methods allow you to update the value of an existing key or add a new key-value pair to the map with a computed value. - merge() method: This method allows you to merge the values of two keys in the map using a specified function. - Improved scalability: The internal data structure and algorithms of ConcurrentHashMap have been improved to support better scalability and reduce contention among threads. Overall, ConcurrentHashMap is a highly efficient and scalable implementation of Map interface that is well-suited for concurrent applications with high throughput and low contention.

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

进击的猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值