HashMap jdk1.8 jdk1.7 put(k,v)---改动

今天看HashMap的源码,主要想看下HashTable和HashMap在放置entry时数据结构的处理方式;

但是我直接打开的是jdk1.8.172版本的源码,怎么看HashMap 的源码都和原来看过记忆中的不太一样,比原来的的方式更加优化,一看版本才发现缘由;

区别:

之前hashmap处理冲突单纯使用链表法进行链接,1.8中,当一散列值中对应的链表长度超过8个后,会将链表转化为红黑树进行存储。

不多说,直接上代码:

1.8之前:

/**
 * Associates the specified value with the specified key in this map.
 * If the map previously contained a mapping for the key, the old
 * value is replaced.
 */
public V put(K key, V value) {
    if (table == EMPTY_TABLE) {
        inflateTable(threshold);
    }
    if (key == null)
        return putForNullKey(value);
    int hash = hash(key);
    int i = indexFor(hash, table.length);
    //这里的循环是关键
    //当新增的key所对应的索引i,对应table[i]中已经有值时,进入循环体
    for (Entry<K,V> e = table[i]; e != null; e = e.next) {
        Object k;
        //判断是否存在本次插入的key,如果存在用本次的value替换之前oldValue,相当于update操作
        //并返回之前的oldValue
        if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
            V oldValue = e.value;
            e.value = value;
            e.recordAccess(this);
            return oldValue;
        }
    }
    //如果本次新增key之前不存在于HashMap中,modCount加1,说明结构改变了
    modCount++;
    addEntry(hash, key, value, i);
    return null;
}

1.8源码:

public V put(K key, V value) {
        return putVal(hash(key), key, value, false, true);
    }
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                  boolean evict) {
       Node<k,v>[] tab; Node<k,v> p; int n, i;
       //如果tab为空或长度为0,则分配内存resize()
       if ((tab = table) == null || (n = tab.length) == 0)
           n = (tab = resize()).length;
       //(n - 1) & hash找到put位置,如果为空,则直接put
       if ((p = tab[i = (n - 1) & hash]) == null)
           tab[i] = newNode(hash, key, value, null);
       else {
           Node<k,v> e; K k;
           //第一节节点hash值同,且key值与插入key相同
           if (p.hash == hash &&((k = p.key) == key || (key != null && key.equals(k))))
               e = p;
           else if (p instanceof TreeNode)//属于红黑树处理冲突
               e = ((TreeNode<k,v>)p).putTreeVal(this, tab, hash, key, value);
           else {
               //链表处理冲突
               for (int binCount = 0; ; ++binCount) {
                   //p第一次指向表头,以后依次后移
                   if ((e = p.next) == null) {
                       //e为空,表示已到表尾也没有找到key值相同节点,则新建节点
                       p.next = newNode(hash, key, value, null);
                       //新增节点后如果节点个数到达阈值,则将链表转换为红黑树
                       if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
                           treeifyBin(tab, hash);
                       break;
                   }
                   //容许null==null
                   if (e.hash == hash &&((k = e.key) == key || (key != null && key.equals(k))))
                       break;
                   p = e;//更新p指向下一个节点
               }
           }
           //更新hash值和key值均相同的节点Value值
           if (e != null) { // existing mapping for key
               V oldValue = e.value;
               if (!onlyIfAbsent || oldValue == null)
                   e.value = value;
               afterNodeAccess(e);
               return oldValue;
           }
       }
       ++modCount;
       if (++size > threshold)
           resize();
       afterNodeInsertion(evict);
       return null;
   }

区别很明显,在数据检索的性能上又提高了不少;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值