zoukankan      html  css  js  c++  java
  • HashMap底层原理分析(put、get方法)

    1、HashMap底层原理分析(put、get方法)

    HashMap底层是通过数组加链表的结构来实现的。HashMap通过计算key的hashCode来计算hash值,只要hashCode一样,那hash值就是相同的。当hash值相同时,就会出现hash冲突,HashMap通过链表来解决冲突。

    原理图:

    实例:

    import java.util.HashMap;
    import java.util.Map;
    ​
    public class HashMapTest {
        public static void main(String[] args) {
            Map<String, String> map = new HashMap<>();
            map.put("fruit", "apple");
            System.out.println(map.get("fruit"));

    1、put方法分析

    //添加键值对方法
    public V put(K key, V value) {
            //如果key为null,则hash值为0,将这个entry放在索引为0的地方,即table[0]
            if (key == null)
                return putForNullKey(value);
            //key不为null
            int hash = hash(key.hashCode());//计算key的hashCode的hash值
            int i = indexFor(hash, table.length);//返回hash值所在的索引位置
            //遍历table[i]处的Entry,若存在key相同并且hash值相同,则用新元素替换旧元素
            for (Entry<K,V> 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);
                    return oldValue;
                }
            }
           //修改标记+1,然后进行元素添加操作
            modCount++;
            addEntry(hash, key, value, i);//将包含特定key、value和hash值的entry添加到特定的桶中
            return null;
        }
    
        //添加key为null的元素
        private V putForNullKey(V value) {
            for (Entry<K,V> e = table[0]; e != null; e = e.next) {
                if (e.key == null) {
                    V oldValue = e.value;
                    e.value = value;
                    e.recordAccess(this);
                    return oldValue;
                }
            }
            modCount++;
            addEntry(0, null, value, 0);
            return null;
        }
        /**
         * Adds a new entry with the specified key, value and hash code to
         * the specified bucket.  It is the responsibility of this
         * method to resize the table if appropriate.
         *
         * Subclass overrides this to alter the behavior of put method.
         */
        void addEntry(int hash, K key, V value, int bucketIndex) {
            Entry<K,V> e = table[bucketIndex];
            table[bucketIndex] = new Entry<>(hash, key, value, e);
            if (size++ >= threshold)
                resize(2 * table.length);
        }

    2、get方法分析

    /**
    * 返回映射的key对应的value值,若map不包含该key,返回null
    */
    public V get(Object key) {
            if (key == null)//获取key为null的value值
                return getForNullKey();
            int hash = hash(key.hashCode());//计算key的hashCode的hash值
            //遍历数组中对应hash值的Entry链表,若Entry元素的hash值与hashCode的hash值相等并且key与查找的key相等,则返回此Entry元素的value值
            for (Entry<K,V> e = table[indexFor(hash, table.length)];
                 e != null;
                 e = e.next) {
                Object k;
                if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
                    return e.value;
            }
            return null;
        }
  • 相关阅读:
    给jquery 添加触屏事件,上下左右 touchwipe插件
    node.js 安装运行
    CSS3 3D 盒子模型
    javascript 获取内联样式
    HTML5 离线存储应用案例
    swipe.js 轻松实现手机端滑动效果
    手机网页轮播切换,简易版
    多行文字垂直居中
    jquery实现简单轮播
    利用media query写响应式布局
  • 原文地址:https://www.cnblogs.com/stm32stm32/p/9035519.html
Copyright © 2011-2022 走看看