• HashTable的数据结构分析(jdk8)


    看了下HashTable的数据结构,继承了Dictionary一个比较过时的抽象类,简单记下原理。

    先看下HashTable的成员变量

        //存放数据的数组,Entry是HashMap.Node实现的接口,基本类似
        private transient Entry<?,?>[] table;
        //存放的对象数量
        private transient int count;
        //扩容阈值
        private int threshold;
        //hashtable的加载因子
        private int threshold;
        //操作数
        private transient int modCount = 0;
    
    

    看下存数据的方法

        //使用synchronized修饰了put方法
        public synchronized V put(K key, V value) {
            // Make sure the value is not null
            if (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];
            // 如果entry已存在,才会走这里,并且也是hash和key都相同才会认为是相同的,这里没有hashmap的onlyIfAbsent
            for(; entry != null ; entry = entry.next) {
                if ((entry.hash == hash) && entry.key.equals(key)) {
                    V old = entry.value;
                    entry.value = value;
                    return old;
                }
            }
            //如果未找到相同的entry 就新增一个
            addEntry(hash, key, value, index);
            return null;
        }
    
        private void addEntry(int hash, K key, V value, int index) {
            //操作数加1
            modCount++;
    
            Entry<?,?> tab[] = table;
            //该扩容了
            if (count >= threshold) {
                // Rehash the table if the threshold is exceeded
                rehash();
                //将新table赋给tab,重新计算hash和index索引
                tab = table;
                hash = key.hashCode();
                index = (hash & 0x7FFFFFFF) % tab.length;
            }
            
            // 新建一个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;
    
            // 处理溢出情况
            //扩容为2倍+1
            int newCapacity = (oldCapacity << 1) + 1;
            // 扩容后长度大于0x7fffffff-8
            if (newCapacity - MAX_ARRAY_SIZE > 0) {
                //如果旧容量已经是最大了,直接返回
                if (oldCapacity == MAX_ARRAY_SIZE)
                    return;
                //新容量不会超过最大值
                newCapacity = MAX_ARRAY_SIZE;
            }
            Entry<?,?>[] newMap = new Entry<?,?>[newCapacity];
    
            modCount++;
            //扩容阈值,最大不会超过最大值+1
            threshold = (int)Math.min(newCapacity * loadFactor, MAX_ARRAY_SIZE + 1);
            table = newMap;
            
            //从数组尾部朝前 重新计算一遍索引 然后放到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;
                }
            }
        }
    
    
  • 相关阅读:
    378. Kth Smallest Element in a Sorted Matrix
    372. Super Pow
    357. Count Numbers with Unique Digits
    345. Reverse Vowels of a String
    343. Integer Break
    347. Top K Frequent Elements
    344. Reverse String
    338. Counting Bits
    326. Power of Three
    python练习
  • 原文地址:https://www.cnblogs.com/june777/p/11720455.html
Copyright © 2020-2023  润新知