• HashMap的get和put操作


    首先来看一下HashMap的构成

    HashMap有

    table Entry[]; 存放key/value值得数组

    size:int 容量

    threshold:int 扩容阈值

    holdfactor:float 扩容参数

    table的一个index对应于同一个hash值,所以

    get方法:

    public V get(Object key) {
        if (key == null)
            return getForNullKey();
        int hash = hash(key.hashCode());
        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;
    }
    

    put方法

    public V put(K key, V value) 
     { 
    	 // 如果 key 为 null,调用 putForNullKey 方法进行处理
    	 if (key == null) 
    		 return putForNullKey(value); 
    	 // 根据 key 的 keyCode 计算 Hash 值
    	 int hash = hash(key.hashCode()); 
    	 // 搜索指定 hash 值在对应 table 中的索引
     	 int i = indexFor(hash, table.length);
    	 // 如果 i 索引处的 Entry 不为 null,通过循环不断遍历 e 元素的下一个元素
    	 for (Entry<K,V> e = table[i]; e != null; e = e.next) 
    	 { 
    		 Object k; 
    		 // 找到指定 key 与需要放入的 key 相等(hash 值相同
    		 // 通过 equals 比较放回 true)
    		 if (e.hash == hash && ((k = e.key) == key 
    			 || key.equals(k))) 
    		 { 
    			 V oldValue = e.value; 
    			 e.value = value; 
    			 e.recordAccess(this); 
    			 return oldValue; 
    		 } 
    	 } 
    	 // 如果 i 索引处的 Entry 为 null,表明此处还没有 Entry 
    	 modCount++; 
    	 // 将 key、value 添加到 i 索引处
    	 addEntry(hash, key, value, i); 
    	 return null; 
     } 
    

    每个 Map.Entry 其实就是一个 key-value 对,从上面程序中可以看出:当系统决定存储 HashMap 中的 key-value 对时,完全没有考虑 Entry 中的 value,仅仅只是根据 key 来计算并决定每个 Entry 的存储位置。这也说明了前面的结论:我们完全可以把 Map 集合中的 value 当成 key 的附属,当系统决定了 key 的存储位置之后,value 随之保存在那里即可。 

    根据上面 put 方法的源代码可以看出,当程序试图将一个 key-value 对放入 HashMap 中时,程序首先根据该 key 的 hashCode() 返回值决定该 Entry 的存储位置:如果两个 Entry 的 key 的 hashCode() 返回值相同,那它们的存储位置相同。如果这两个 Entry 的 key 通过 equals 比较返回 true,新添加 Entry 的 value 将覆盖集合中原有 Entry 的 value,但 key 不会覆盖。如果这两个 Entry 的 key 通过 equals 比较返回 false,新添加的 Entry 将与集合中原有 Entry 形成 Entry 链,而且新添加的 Entry 位于 Entry 链的头部 

  • 相关阅读:
    IDEA使用-多线程调试
    IDEA使用-设置条件断点
    msyql定时备份数据库
    Jenkins配置详解
    Redis学习笔记
    if/else的几种优化方式
    【Linux】开放指定端口
    IDEA首次使用Git
    Navicat 快捷键使用
    IDEA远程调试Linux服务器上代码
  • 原文地址:https://www.cnblogs.com/TaoChiangBlog/p/6533072.html
Copyright © 2020-2023  润新知