复习一下hashMap

      最近新头头问了问我HashMap,写Wrapper时间久了,以前的东西忘了好多,回来复习了一下,总结如下,不对的求指正:
1 HashMap的数据结构
数据结构中有两种基本的存储结构,数组和链表,这两个基本是就是两个极端
a,数组  
数组的存储结构是连续的,内存浪费严重,空间复杂度高,但查找操作的时间复杂度很低,为O(1),所以数据:寻址容易,add()和delete()困难
b,链表
链表的存储结构是离散的,内存浪费低,(我感觉这可以降低内存中的碎片生成,操作系统里看到的东西,不知道这样分析对不对)但查找操作的时间复杂度达到O(N),所以链表:寻址困难,add()和delete()容易
HashMap用“拉链法”实现出来的下图这样,这货是杂交出来的集大成者--链表的数组


复习一下hashMap

复习一下hashMap
这些数据如何存储到数组中的呢,可以通过hash(key)%length来得出在数组中的具体位置,如何图中数组index为12的几个entry,他们的中的key的hash(key)都是12

HashMap内部有一个entry的内部类,重要的属性包含key,value,next,这是一个HashMap键值对的基本bean,所以上图中数组其实就是一个entry[],map中的内容对放在entry[ ]中

    transient Entry[] table 

至于 transient 的意思 附个链接http://www.cnblogs.com/lanxuezaipiao/p/3369962.html,好像是数据序列化时用的,还没细读

 


  1. staticclass Entry implements Map.Entry {
  2.        final Kkey;
  3.        Vvalue;
  4.        Entrynext;
  5.        inthash;

  6.      
  7.        Entry(inth, K k, V v, Entry n) {
  8.           value = v;
  9.           next = n;
  10.           key = k;
  11.           hash = h;
  12.       }

 

这里注意一点,当两个hash(key)&length结果一下时,会加入到上图的那个链表中,新来的加入到表头,最先来的实际是在最后的位置上。

还有一个要注意,hash(key)和hashcode(key)好像不是一回事,代码如下
  1.  
  2.    final int hash(Object k) {
  3.        int h =hashSeed;
  4.        if (0 != h&& k instanceof String) {
  5.           returnsun.misc.Hashing.stringHash32((String) k);
  6.       }

  7.        h ^=k.hashCode();

  8.        // Thisfunction ensures that hashCodes that differ only by
  9.        //constant multiples at each bit position have a bounded
  10.        // numberof collisions (approximately 8 at default load factor).
  11.        h ^= (h>>> 20) ^ (h >>> 12);
  12.        return h ^(h >>> 7) ^ (h >>> 4);
  13.    }


2   hash算法
我们要在hashmap中找到某个value,需要根据key的hash值来找到对应数组的位置,怎么计算这个位置就是hash算法,“拉链法”实现的hashmap是由数组和指针杂交的,我们需要让他们分布的更加均匀些,尽量每个位置对应的元素只有一个,这样找到数组的位置是直接就能得到value了,不用去遍历链表,现在问题来了,怎么办?
首先想到的是hashcode(key)%length,这样分布的均匀些,但取”模“运算消耗还是很大,java中是这样实现的
  1.    static int indexFor(int h, int length){
  2.        // assertInteger.bitCount(length) == 1 : "length must be a non-zero power of2";
  3.        return h& (length-1);
  4.    }
取得key的hashcode然后和数组长度&一下,简直牛逼!!!这就可以很清楚的看出来为什么hasmap的初始数组长度要是2的幂了


看到了吧这样非常有效的降低了发生碰撞的可能性,分布也就更加均匀,效率提升不小吧!
所以Java中最好指定2的幂为数组的大小,就算你不指定,Java也是按照比指定值大切最接近指定值得2的幂那个值来做初始大小的---指定值为3,Java中就给你改成4了
  1. int capatity = 1;
  2. while(capatity 
  3. capatity <<=1;
  4. }







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值