本文已参与「新人创作礼」活动,一起开启掘金创作之路。
早上在看毕设项目时,突然注意到在处理一些数据时,用到了 HashMap,Map的应用在之前公司实习时,有使用过,但突然一下在毕设中看到没怎么太想起来怎么用的了,今天再总结一下...........
引
Java中对象存储容器有ArrayList,LinkedList,HashSet等,HashMap 相对这些容器来说,可以理解为多了一层指向关系,可以用指定Key找到指定Value。
HashMap
采用数组存储数据,查询快,插入和删除困难; 采用链表存储数据,查询慢,插入和删除比较容易;
HashMap是由数组和链表组成的,又叫链表散列。满足: 快速存储(get()和put()方法); 快速查找(通过 key 去 get 一个value 时间复杂度非常低,效率非常高); 可伸缩(数组扩容;JDK 1.8单向链表如果长度超过8会演变成红黑树) HashMap 默认负载因子是 0.75,也就是 75%,HashMap 初始长度默认是16,阈值 = 当前长度 * 0.75,当当前长度大于或等于阈值时会进行自动扩容。
Hash 算法
key.hashCode() 与 key.hashCode>>>16(右移 16 位) 进行异或运算。
Hash 冲突
就是键 key,经过 hash 得到的结果之后去存 key-value 键值对的时候,发现该地址已经存了值 value,就发生了冲突,即 hash 冲突。
负载因子 0.75
如果过大,加入是 1,也就是 HashMap 的容量必须要全部装满才允许扩容,但如果 HashMap 容量全部装满,就会产生大量 Hash 冲突,put、get 操作效率会下降;如果过小,假如 0.5,虽然减少了 Hash 冲突,但有一半的空间没有利用,造成空间利用率低下。至于 0.75,也并不是随便产生的,根据牛顿二项式,计算得到 0.693,选用 0.75(即, 3/4)为了使算出来的容量是整数。每次扩容都是 2 的整数次幂,跟 3/4 计算保证得到整数。
初始容量是16
看 HashMap 源码可知道,当新 put 一个数据时,会计算其位于 table 数组,也就是桶中的下标:int index = key.hashCode&(length-1),因为是将二进制进行按位与运算, 16 - 1 = 15,二进制 1111,末位是 1,能保证计算后的下标既可以是奇数也可以是偶数,就会减少重复,减少 Hash 碰撞。理论上只要是二的整数次幂都可以,但如果是 4或者 8,很容易导致 map 扩容影响性能,太大又会浪费资源。
简单总结一下,现在看来 HashMap 的使用率还是比较高的,包括之前在实习时,利用 map 的 key-value 特点来接受 JSON 对象。虽然是可行,但不知道那样写对不对,有问题请指正。
我向你敬礼啊,Salute!