HashMap介绍
HashMap是一个基于数组+单向链表的一个集合,存储方式为键值对,在JDK1.8之后变为数组+单向链表+红黑树,HashMap是线程不安全的,多线程下,JDK1.7会造成闭环,JDk1.8会覆盖数据,多线程环境下建议使用ConcurrentHashMap。
HashMap使用(会用的直接跳过)
经常使用的方法
Map<String,Integer> map = new HashMap();
//put
map.put("张三",18);
map.put("李四",20);
map.put("王五",22);
//get
map.get("张三"); //运行结果 18
//containsKey
map.containsKey("张三") //运行结果 true
map.containsKey("赵六") //运行结果 false
//size
map.size(); //运行结果 3
//下面介绍一下map的循环
//1、这个方式也是map的普通循环方式
Set<Map.Entry<String, String>> entrySet = map .entrySet();
for (Map.Entry<String, String> map: entrySet) {
System.out.println(map.getKey()+"-->"+map.getValue());
}
//2、jdk1.8的lambda的方式
map.forEach((k,v) -> {
System.out.println(k+"-->"+v);
})
jdk1.7和jdk1.8变化
JDK1.7
数组+单向链表
问题:
JDK1.8
数组+单向链表+红黑树
好处
红黑树分析推荐看这篇文章
https://blog.csdn.net/ThinkWon/article/details/102571535
底层原理
HashMap扩容机制
HashMap初始大小是16,达到扩容条件(阈值)之后,进行二倍扩容
什么时候才进行扩容(阈值)?
当数组长度达到负载因子的时候就会进行二倍扩容,数组长度默认16,负载因子默认0.75也就是达到12(阈值)的时候就会扩容
为什么负载因子设定是0.75呢?
这个我自己理解的是,如果设置的偏小,比如0.6那么感觉有点浪费资源,因为还有很多空位没有存放值就进行了扩容,相当于没有合适利用资源,那如果设置的比较大比如0.9,那就要用到14.4,也就相当于快满了才会进行扩容,这个就又能导致某些数组下标后的单向链表非常多,所以我的理解是取中
HashMap存储方法
当我们查看put方法的时候可以看到:
有一个hash(key),那么这个hash方法是用来干什么呢,既然它存在于put中,那么就说明他是要存储于集合中,存储方式就是要计算hash值来均匀分布在数组中
hash(key)计算
是一个三元运算符,如果key是null那就默认是0,也就是存储在数组0的位置,key也就是null但是只能存储一个key为null的,这个也很好理解,因为key是不能重复的,所以如果有第二个key为null的,他依然会存储于数组下标为0的位置,那么就会覆盖掉上一次的值,而value是可以为null的,比如:
那如果key不是null呢,那就是后面的计算方式,位运算法
这样计算能更好的分布于数组中,减少hash碰撞
总结
上面是我个人对HashMap的理解,内容比较少,也没有去讲解源码,这些基本上就是HashMap的表层知识,刚开始写博客,希望大家多多关照
另外给大家一个好玩的网站,这个网站里面可以动态的查看B-Tree,B+Tree,红黑树等组建过程
https://www.cs.usfca.edu/~galles/visualization/Algorithms.html
喜欢点个赞在走!