zoukankan      html  css  js  c++  java
  • HashMap原理和TreeMap原理

    http://www.importnew.com/7099.html及文章下方评论

    http://blog.csdn.net/vking_wang/article/details/14166593超赞

    http://blog.csdn.net/ghsau/article/details/16890151容量加载因子

    HashMap数据结构用数组和链表形式实现:

    每个数组中存储的是链表的头元素。每个元素是个entry,包含键和值。

    hashmap的get(key)方法得到的是key对应的value,并不是key-value键值对。

    用了hashing(哈希算法)来查找???(目前来看查找没有完全用哈希算法)

    调用put方法存储元素时,会先调用hashcode()方法返回键的hashcode,键的hashcode对数组的长度进行取余运算,得到的值便是桶的位置,比如两个元素的key的hashcode为12和28,数组长度为16,取余的结果都是12,将一起存储在数组下标为12的位置,存储entry实体(不是只存储值哦)。之后调用Map.entry可以获取。

    上面hashcode为12和28的key,其对应实体往下标相同的数组中put时怎么put?任何一个元素进来存在数组(数组中存的是最后一个插入的元素),并且该数组的元素有entry属性,其中的next会指向前一个存在数组中的元素。

    HashMap有两个参数影响其性能:初始容量和加载因子。默认初始容量是16还是2的冪次????,加载因子是0.75。容量是哈希表中桶(Entry数组)的数量。初始容量是哈希表创建时的容量,加载因子是哈希表在其容量自动增加前可以达到多满的一种尺度。当哈希表中条目数????超出了加载因子与当前容量的乘机,通过调用rehash方法将容量翻倍。

    void addEntry(int paramInt1, K paramK, V paramV, int paramInt2)
    {
    Entry localEntry = this.table[paramInt2];
    this.table[paramInt2] = new Entry(paramInt1, paramK, paramV, localEntry);
    if (this.size++ >= this.threshold)
    resize(2 * this.table.length);
    }

    覆盖和哈斯算法,16还是2的冪次???????concurrentHashMap和hashtable的区别,set存相同的情况,覆盖equals()需要覆盖hashCode()?

    对hashcode()方法进行再哈希的原因:

    本身hashcode是一个int型的值,取值范围有40多亿空间。只要哈希函数映射比较均匀松散,一般不会出现哈希碰撞。但是!由于想把各个对象均匀的分不到hashmap的桶中,因此需要对hashcode做取模运算,取模运算保留的是低位区的数字,比如hashmap桶的数量为16时,对hashcode取模保留的是低四位的数字。对于两个对象的hashcode,32位的hashcode一样的情况少,但它们的低四位一样的情况概率挺大的,因此必须对hashcode的低位增加随机性。可以直接对低位使用随机函数,因此采用高低位进行异或运算来增加低位的随机性,以便对象可以在不同的桶中随机分布。

    java中%表示取余

    取余和取模的区别是:在计算商时,取余向正方向舍入得到商,取模则是向负方向舍入得到商。(取模运算必须至少用一个double型做除法,两个int型的数除法只是取整,整数取模的结果有问题)

    当除数与被除数的符号相同时,rem和mod的结果是完全相同的;当除数与被除数的符号不相同时,结果不同。
    具体说,rem结果的符号与被除数相同;mod结果的符号与除数相同。
     
    hashmap中添加元素:
    public V put(K key, V value) {
         // 若“key为null”,则将该键值对添加到table[0]中。
             if (key == null) 
                return putForNullKey(value);
         // 若“key不为null”,则计算该key的哈希值,然后将其添加到该哈希值对应的链表中。
             int hash = hash(key.hashCode());
         //搜索指定hash值在对应table中的索引
             int i = indexFor(hash, table.length);
         // 循环遍历Entry数组,若“该key”对应的键值对已经存在,则用新的value取代旧的value。然后退出!
             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))) { //如果key相同则覆盖并返回旧值
                      V oldValue = e.value;
                     e.value = value;
                     e.recordAccess(this);
                     return oldValue;
                  }
             }
         //修改次数+1
             modCount++;
         //将key-value添加到table[i]处
         addEntry(hash, key, value, i);
         return null;}


    hashset添加元素

    public boolean add(E paramE)
    {
    return this.map.put(paramE, PRESENT) == null;
    }

    由此知当hashset添加重复元素会返回null(因为hashmap添加key相同的元素时更新value后返回原始value而不是null)

     

    hashmap根据key获取元素:

    2)get

    
    
     public V get(Object key) {
    
    
            if (key == null)
    
    
                return getForNullKey();
    
    
            int hash = hash(key.hashCode());
    
    
            //先定位到数组元素,再遍历该元素处的链表(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;
    
    
    }
     
    hash():
    static final int hash(Object key) {
    int h;
    
    
    return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    
    
    }
    hashcode右移16位左边补0后与原hashcode异或运算增加低位随机性。 


    TreeMap
    TreeMap基于红黑树实现
    主要用于存入元素的时候对元素进行自动排序,迭代输出的时候就按排序顺序输出。
    TreeMap中key不能为null
    http://www.cnblogs.com/wzyxidian/p/5204879.html
    新生的小心情
  • 相关阅读:
    Java学习笔记(4)
    Idea常用功能汇总
    Java学习笔记(3)
    Java学习笔记(2)
    Java学习笔记(1)
    如何开发NPM包
    c#抓屏功能在DPI缩放后,截到的图片不完整的问题
    支持续传功能的ASP.NET WEB API文件下载服务
    ASP.NET MVC 阻止通过Url直接访问服务器上的静态文件
    VS2013/VS2015/VS2017通过oschina托管代码
  • 原文地址:https://www.cnblogs.com/jianmianruxin/p/7505694.html
Copyright © 2011-2022 走看看