美文网首页
HashMap源码分析

HashMap源码分析

作者: 哦00 | 来源:发表于2019-01-29 15:25 被阅读0次

    HashMap

    JDK1.7 和1.8中关于对HashMap的实现,有了一些变化,其中很重要的一个变化,就是在解决Hash冲突的时候,存储数据结构有所调整。

    1.7版本:

    主要实现方式: 通过数组+ 链表的方式实现。当hash冲突的时候,使用链表来解决冲突。但是当hash不均匀的时候,可能会导致数据倾斜到某个数组槽位。那么对集合的更新、查找操作最后转变为线性查找,失去了hash查找的特性。

    //使用数组式的链表,如果key的hash值一样,则通过List结构来解决冲突,当hash不均匀,可能会导致最后的数据变为线性查找List,性能无法保证transient Entry[]table;staticclassEntryimplementsMap.Entry {finalK key;        V value;        Entry next;inthash;/**其他方法**/}    public V put(K key, V value) {if(key ==null)returnputForNullKey(value);inthash = hash(key);inti = indexFor(hash,table.length);//当该数组的hash槽位有数据时,则通过链表的方式追加到链表的结尾for(Entry e =table[i]; e !=null; e = e.next) {            Object k;if(e.hash== hash && ((k = e.key) == key || key.equals(k))) {                V oldValue = e.value;                e.value= value;                e.recordAccess(this);returnoldValue;            }        }        modCount++;        addEntry(hash, key, value, i);returnnull;    }voidaddEntry(inthash, K key, V value,intbucketIndex) {if((size >= threshold) && (null!=table[bucketIndex])) {            resize(2*table.length);            hash = (null!= key) ? hash(key) :0;            bucketIndex = indexFor(hash,table.length);        }        createEntry(hash, key, value, bucketIndex);    }voidcreateEntry(inthash, K key, V value,intbucketIndex) {        Entry e =table[bucketIndex];table[bucketIndex] =newEntry<>(hash, key, value, e);        size++;    }

    1.8 版本

    在1.8的版本中,同样是通过数组+链表的方式存储结构。但是1.7的Entry 被命名为Node,并且 当Node容量到达8的时候,会将Node转换为TreeNode(红黑树结构),查找效率大大提高

    /**

        * Basic hash bin node, used for most entries.  (See below for

        * TreeNode subclass, and in LinkedHashMap for its Entry subclass.)

        */staticclassNodeimplementsMap.Entry{finalinthash;finalK key;        V value;        Node next;/**其他方法**/}finalVputVal(inthash, K key, V value,booleanonlyIfAbsent,booleanevict){        Node[] tab; Node p;intn, i;if((tab = table) ==null|| (n = tab.length) ==0)            n = (tab = resize()).length;//不存在,直接新建并赋值到数组对应槽位if((p = tab[i = (n -1) & hash]) ==null)            tab[i] = newNode(hash, key, value,null);else{            Node e; K k;//如果已经有该key值,则直接返回该Nodeif(p.hash == hash &&                    ((k = p.key) == key || (key !=null&& key.equals(k))))                e = p;//如果该Node 是TreeNode,则直接放入到TreeNode结构中elseif(pinstanceofTreeNode)                e = ((TreeNode)p).putTreeVal(this, tab, hash, key, value);else{for(intbinCount =0; ; ++binCount) {if((e = p.next) ==null) {                        p.next = newNode(hash, key, value,null);//如果该槽位的值大于等于7的时候,需要转换成TreeNode数据结构来存储;TREEIFY_THRESHOLD等于8if(binCount >= TREEIFY_THRESHOLD -1)// -1 for 1sttreeifyBin(tab, hash);break;                    }if(e.hash == hash &&                            ((k = e.key) == key || (key !=null&& key.equals(k))))break;                    p = e;                }            }if(e !=null) {// existing mapping for keyV oldValue = e.value;if(!onlyIfAbsent || oldValue ==null)                    e.value = value;                afterNodeAccess(e);returnoldValue;            }        }        ++modCount;if(++size > threshold)            resize();        afterNodeInsertion(evict);returnnull;    }/**

        * 将Node数组中,对应hash槽位的Node转换为TreeNode数据结构

        *

        * Replaces all linked nodes in bin at index for given hash unless

        * table is too small, in which case resizes instead.

        */finalvoidtreeifyBin(Node[] tab,inthash){intn, index; Node e;if(tab ==null|| (n = tab.length) < MIN_TREEIFY_CAPACITY)            resize();elseif((e = tab[index = (n -1) & hash]) !=null) {            TreeNode hd =null, tl =null;do{                TreeNode p = replacementTreeNode(e,null);if(tl ==null)                    hd = p;else{                    p.prev = tl;                    tl.next = p;                }                tl = p;            }while((e = e.next) !=null);if((tab[index] = hd) !=null)                hd.treeify(tab);        }                                                                                                                 欢迎工作一到五年的Java工程师朋友们加入Java群: 741514154

    群内提供免费的Java架构学习资料(里面有高可用、高并发、高性能及分布式、Jvm性能调优、Spring源码,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多个知识点的架构资料)合理利用自己每一分每一秒的时间来学习提升自己,不要再用"没有时间“来掩饰自己思想上的懒惰!趁年轻,使劲拼,给未来的自己一个交代!

    相关文章

      网友评论

          本文标题:HashMap源码分析

          本文链接:https://www.haomeiwen.com/subject/lxpxsqtx.html