HashMap,Hashtable区别

         HashMap                                                                                                       Hashtable

空:key,value都可空                                                                                   key可空,value为空抛出异常,

重:key重复会覆盖之前的value,                                                               key重复会覆盖之前的value,

序:无序,                                                                                                    无序(有序和无序的源头是HashMap和Hashtable是通过什么方式存储数据的,Entry<K,V>链表以 及table数组,怎么是实现的看源码)

        安:线程不安全                                                                                            线程安全(基本每个方法前加关键字synchronized)-(能说出synchronized和lock()的区别么?)

 

1.HashMap的初始化

在jdk1.7中,HashMap的默认初始化中,分配的数组大小为16。

default_initial_capacity= 16;

maximum_capacity =1<<30; (2^30 =1073741824)

default_loader_factor= 0.75f;

底层是链表的数组,key的引用地址放在数组中,数据放在链表里,数组放链表的头,

比如int[] its = new int[16];

按照hash(key)%16 = x,则Entry<key,value>就放在x中的一个位置,;

为什么要用数组和链表的结合呢? 因为数组适合数据的查找,在增删数据的时候需要移动组内元素,所以速度较慢,而链表在查找数据的时候较慢,而增删数据只需要移动指针就可以,所以两者的结合使得HashMap有较快的查数据和增删数据能力。

 

下面我们来认识HashMap的底层实现,数组加链表是HashMap的底层实现,通过一个Table来管理每个链表的头,每个链表的头怎么选择key呢?看下面的源码。

 

public V put(Kkey,V value){

...

int hash =hash(key);

int i =indexFor(hash, table.length);

         ...}

 

key在被put时,先hash()方法,该方法对key做位计算,求出哈希值,再通过indexFor()求出在数组中,这个key放在哪个位置处,通过hash%table.length取余,比如:

         Map<String,int>map = new HashMap(16);

         m.put(key1,"1")';

         m.put(key2,"2");

         m.put(key3,"3");

         m.put(key4,"4");

我创建了一个数组大小为16的HashMap,四个key的hash值算出来分别是16,17,32,18;那么执行hash%table.length之后,分别是0,1,0,2,所以放的位置分别是table[0],table[1],table[0],table[2]。

 

所以四个值是这么放的。

每次put先回去判断是否key为空,如果空,那么执行putForNullKey(),再判断是否已经有同一个key存在,如果存在则将原来的value返回,并将新的value保存到对应的key处,

一个table数组                

Entry<k,v>链表    每一个椭圆代表的是一个Entry<k,v>对象,而一个方块就是Entry<k,v>[0]因为链表的内容就是Entry<k,v>,通过一个HashMap$Entry对象的next变量来串联起多个Entry形成一个链表。

public V put(K key, V value) {

    if (table ==EMPTY_TABLE) inflateTable(threshold); -------------1-------

        if (key== null) return putForNullKey(value);----------------------2-------

        int hash= hash(key);

        int i =indexFor(hash, table.length);-------return hash & (table.length-1)--------

        for(Entry<K,V> e = table[i]; e != null; e = e.next) {---------------3-------

            Objectk;

            if(e.hash == hash && ((k = e.key) == key || key.equals(k))) {-4-----

                VoldValue = e.value;

                e.value= value;

                e.recordAccess(this);

                returnoldValue;----------------------------------------------5-------

            } }

    modCount++;------------------------------------------------------6------

    addEntry(hash,key, value, i);---------------------------------------7-----

    return null;

}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值