HashMap 源码分析(1.7)
概念HashMap是基于hash表的map实现类,它可以接收null的键值,是非线程安全的,底层基于数组加链表实现,1.8后到场了红黑树,HashMap底层维护了长度为16的Entry数组(长度是可以指定),我们使用hashmap存储数据的时候 会根据 key的hashcode方法计算出hash值 根据hash值及数组的长度取模能够计算出 要存入数组中的下标位置,数据里面的每个位置都称作bucket桶。一个桶有可能会存放多个Entry (hash碰撞) ,多个Entry会已单向链表形式存放。如果指定下标的bucket不存在单向链表,则直接存入。如果存在遍历单向链表,对比key 是否equals . 如果发现有相同的key, 覆盖原来的内容。 如果不存在则将当前的entry追加到单向链表中, 如果桶的使用到达一定数量会触发扩容,这个数量是根据负载因子 和 数据长度决定的 (数组长度 负载因子 ),默认的负载因子为0.75 ,默认数组长度为16 乘以 0.75=12,桶的使用凌驾12就会触发扩容 ,扩容会创建一个新的数组 长度为旧数组的2倍 ,并将旧数组中的数据迁入到新数组中。 hashmap不是线程安全的, 如果多线程考虑使用hashTable 或 ConcurrentHashMap 或 Map m = Collections.synchronizeMap(hashMap);put方法源码详解
如果存入的key为null 那这个Entry会存入到0位数组中不为null 管帐算key的hash值根据hash 及 数组长度管帐算出桶的下标查看下标下是否有对应Entry链表,如果有遍历该链表对链表中Entry的key举行equals对比,如果结果为true替换没有对比到对应的key则会将新的Entry插入到链表的表头中什么是哈希碰撞(hash碰撞)
指的是两个不同的key计算出相同的hashcode 称为hash碰撞发生hash碰撞后,他们会存入相同的桶中为什么负载因子要默认为0.75
HashMap负载因子为0.75是 空间和时间 成本的一种折中,负载因子过小,扩容频率变高,空间使用率变低负载因子过高,空间使用率变高,但hash碰撞增加,造成链表长度增加影响查询性能使用时可根据需求更改负载因子get方法详解
根据key的hash方法及数组的长度,找到bucket位置之后,会调用keys.equals()方法去找到链表中正确的节点,最终找到要找的值对象。因此,计划HashMap的key类型时,如果使用不可变的、声明作final的对象,并且采用合适的equals()和hashCode()方法的话,将会减少碰撞的发生,进步服从。不可变性能够缓存不同键的hashcode,这将进步整个获取对象的速度,使用String,Interger这样的wrapper类作为键是非常好的选择扩容详解
插入新的Entry对象时 必要判断size是否大于即是 负载因子*数组长度,如果大于必要先对数组举行扩容,扩容就是用一个新的大数组替换原来的小数组,并将原来数组中的值迁移到新的数组中什么是哈希表?(hash表、散列表)
哈希表(HashTable)又叫做散列表,是根据关键码值(即键值对)而直接访问的数据结构。也就是说,它通过把关键码映射到表中一个位置来访问记录,以加快查找速度。这个映射函数就叫做散列(哈希)函数,存放记录的数组叫做散列表。在数据结构中,我们对两种数据结构应该会非常熟悉:数组与链表。数组的特点就是查找容易,插入删除困难;而链表的特点就是查找困难,但是插入删除容易。既然两者各有优缺点,那么我们就将两者的有点结合起来,让它查找容易,插入删除也会快起来。哈希表就是讲两者结合起来的产物。为什么String、Integer这样的类适合作为key
因为String是不可变的,也是final的,而且已经重写了equals()和hashCode()方法了。因为获取对象的时候要用到equals()和hashCode()方法,那么键对象正确的重写这两个方法是非常告急的。如果两个不相等的对象返回不同的hashcode的话,那么碰撞的几率就会小些,这样就能进步HashMap的性能如果使用自定义的对象作为key要注意什么
一定要重写equals 及 hashcode的方法jdk1.8对于hashmap的优化
[*]单个链表长度凌驾8,数组长度到达64,会采用红黑树结构举行树化,优化查询服从
[*]数组扩容时旧数据的迁移采用位运算 得到的值 为0或1 0位置稳定 1位置为当前位置加原数组长度,避免重新hash的性能开销
[*]1.7hashmap扩容时,采用的是头插法 有可能产生环,1.8后扩容采用的是尾插法,不会产生环
hashmap的线程安全问题
hashmap有线程安全问题,如果想使用线程安全的hashmap可以使用 :HashTable: hashtable 是在方法上加 synchronized关键字包管安全,性能较差ConcurrentHashMap: 采用分段锁的方式包管线程安全,性能更好,推荐使用
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页:
[1]