zoukankan      html  css  js  c++  java
  • 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;
                }
            }
        }
    
    
  • 相关阅读:
    深入了解 Flink 网络栈(二):监控、指标和处理背压
    物联网安全技术提高区块链应用数据的可信度
    威胁快报|Bulehero挖矿蠕虫升级,PhpStudy后门漏洞加入武器库
    Ververica Platform-阿里巴巴全新Flink企业版揭秘
    重磅 | 阿里云与MongoDB达成战略合作,成为全球唯一提供最新版MongoDB的云厂商
    阿里巴巴叶军:政企数字化转型,现在是最重要的时机
    Canonical 开源 MicroK8 | 云原生生态周报 Vol. 25
    nyoj42——连通图加欧拉(连通图板子)dfs
    nyoj38——最小生成树
    nyoj20——有向无环图深搜模板
  • 原文地址:https://www.cnblogs.com/june777/p/11720455.html
Copyright © 2011-2022 走看看