博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
学习笔记2 Haspmap简述
阅读量:4505 次
发布时间:2019-06-08

本文共 1320 字,大约阅读时间需要 4 分钟。

   HashMap基于Map接口实现,数据元素以key-value的形式存在,是由数组加链表组合实现,原理图网上太多,大同小异,就不贴了。

   默认初始容量为16,加认装载因子为0.75。同时,Hashmap提供了三种构造方法,借助这些构造方法也可以自己设置初始容量和装载因子(public HashMap(int initialCapacity, float loadFactor))。

   加载因子0.75指当HashMap中的元素数量达到容量的75%时,需要进行扩容,每次扩容后,容量必须为2的N次方。原因:加载因子过大,如设成0.99,会导致存数据是冲突率极高,不停地在链表上加元素,

读取元素时开销就会很大,加载因子过小,如0.5,虽然冲突率较低,查找速度快,但会导致极大地空间浪费,所以0.75算是个折衷方案,平衡了空间利用率和冲突几率。

   每次扩容后容量必须为2的N次方,原因:这个与HashMap中计算下标的算法有关

static int indexFor(int h, int length) {        return h & (length-1);    }

里边的h是元素的hash码,这行代码的作用是对hash码按HashMap的容量取余,得到的值为HashMap的下标。原因在于这个length-1。如16-1转换成2进制是1111,32-1转换成2进制是11111,所以,容量为2的N次方就是要保证length-1后得到的2进制数末几位全为1。如果不全为1会有什么后果呢?以15为例,15-1转换成2进制是1110,因为代码中做得是按位与运算,  因为末置位为0,不管h的末置位是几&0得到的结果都是0,也就是说末置位为1几种可能是永远得不到。例如1111,1011等,这样就造成了一部分的空间浪费。

HashMap的线程不安全:两个输入元素的key值相同时,会将后存入的元素存到数组中,先进入的元素会添加到链表中,由后存入元素的next属性指向。多线程的时候,如果两个线程同时往HashMap中存元素,恰好两个线程的存的元素的key值相同,而且这两个线程恰好同时取到了对应key的头结点,那么一定会有一个元素丢失,这就是HashMap的线程不安全问题。相对的HashTable是线程安全的,通过每个方法加了sychronized实现,所以效率低下。

JDK中对HashMap的线程不安全问题提供了两种解决方案:(1)通过Collections.synchronizedMap()返回一个新的Map,这个新的map就是线程安全的,注意返回的不是一个HashMap,是一个Map的实现。此方法封装了所有的线程不安全的HashMap方法,调用方法是对整个HashMap同步。(2)ConcurrentHashMap,ConcurrentHashMap采用的是分段锁机制,把Map分成N个Segment,多线程时只需要锁住Segment而不用锁整个Map,极大地提高了效率。其中放入哪个Segment也是通过Hash码计算的。

转载于:https://www.cnblogs.com/HC-blog/p/7384186.html

你可能感兴趣的文章
ui-router 1.0 003 lazyloading
查看>>
Lua编程
查看>>
程序中堆和栈的区别
查看>>
imx6 lvds 代码分析
查看>>
通过代码创建联系人
查看>>
大数智能未来
查看>>
jQuery插件实现网页底部自动加载-类似新浪微博
查看>>
学生空间bug report
查看>>
shanchushanchu
查看>>
linux下使用autoconf制作Makefile
查看>>
快来秒杀我
查看>>
Python_阻塞IO、非阻塞IO、IO多路复用
查看>>
爬虫超时解决的方法
查看>>
网络技术和科技革命周末随想
查看>>
Codeforces 10C Digital Root 法冠军
查看>>
华为-on演习--身高找到最好的二人
查看>>
debian软件安装基础(同tomcat案件)
查看>>
如何面对客户的紧急需求
查看>>
【转载】嵌入式linux学习规划
查看>>
[转帖]和机器学习和计算机视觉相关的数学
查看>>