hashMap 源码解读理解实现原理和hash冲突
hashMap 怎么说呢。 我的理解是 外表是一个set 数组,无序不重复 。 每个set元素是一个bean ,存着一对key value
看看代码吧
package test; import java.util.HashMap;
import java.util.Map.Entry; public class HashMaptest { public static void main(String[] args) { HashMap<String, String> map = new HashMap<String, String>(); String aa = "张三";
String bb = "李四";
map.put(aa, "22");
map.put(bb, "34234");
map.put("张三", "223"); System.out.println(aa.hashCode());
System.out.println(bb.hashCode()); for (Entry<String, String> entry : map.entrySet()) { System.out.println(entry.getKey()); // System.out.println(entry.getValue());
} } }
打印的结果是:
李四
张三
可以看到, 虽然张三是先插进去的, 但是确在后面打印出来,说明这个数组不是有序的, 不是list;
虽然aa 的 hashcode=774889 大于bb 的, 肯定不是根据大小插入的,应该是把 得到的hashcode 取余 , 例如 6%7 = 6 , 9%(7+1)=1 ,6>1 ,所以9 在前面,这里为什么是 第一个除以7 ,第二个进来确实% 8呢;
因为hash算法是 这样的:
int hash = key.hashCode(); // 这个hashCode方法这里不详述,只要理解每个key的hash是一个固定的int值
int index
= hash % Entry[].length;
Entry[index] = value;
这里看到 Entry[].length 一直在增加的;
所以就会遇到hash冲突, 总有碰到取余后一样的;
好了,举个例子:
比如 key="张三", hashcode=666 ,entry的size是 100 666%100=66 ;存在 66 位置上。 这个时候 key="李四" 要插入了, hashcode =6666 entry的size是 6600 6666%6600=66 , 这样 66 位置就hash冲突了;
这里和我代码写的覆盖不是一回事 。 代码的 key 相同,这里在特别说明下:可能有人说, 两个张三的hashcode 一样, 不同时候插入,entry 的 size不是不一样吗, 那就不会覆盖了? 这么想是错误的, 其实 map 插入的时候是先比较equals 的, 发现,咦 ,相同, 直接覆盖原值
:附上 hashMap的Put 方法源码:
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
boolean evict) {
Node<K,V>[] tab; Node<K,V> p; int n, i;
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length;
if ((p = tab[i = (n - 1) & hash]) == null)
tab[i] = newNode(hash, key, value, null);
else {
Node<K,V> e; K k;
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))
e = p;
else if (p instanceof TreeNode)
e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
else {
for (int binCount = 0; ; ++binCount) {
if ((e = p.next) == null) {
p.next = newNode(hash, key, value, null);
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
treeifyBin(tab, hash);
break;
}
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
break;
p = e;
}
}
if (e != null) { // existing mapping for key
V oldValue = e.value;
if (!onlyIfAbsent || oldValue == null)
e.value = value;
afterNodeAccess(e);
return oldValue;
}
}
++modCount;
if (++size > threshold)
resize();
afterNodeInsertion(evict);
return null;
}
可能比较难懂, 主要在这句:
if (e != null) { // existing mapping for key
V oldValue = e.value;
if (!onlyIfAbsent || oldValue == null)
e.value = value;
afterNodeAccess(e);
return oldValue;
}
已存在的key ,之而立是直接覆盖的。
hashMap 源码解读理解实现原理和hash冲突的更多相关文章
- HashMap源码解读(转)
http://www.360doc.com/content/10/1214/22/573136_78188909.shtml 最近朋友推荐的一个很好的工作,又是面了2轮没通过,已经是好几次朋友内推没过 ...
- HashMap源码解读(JDK1.7)
哈希表(hash table)也叫散列表,是一种非常重要的数据结构,应用场景及其丰富,许多缓存技术(比如memcached)的核心其实就是在内存中维护一张大的哈希表,而HashMap的实现原理也常常出 ...
- 深入理解JAVA集合系列一:HashMap源码解读
初认HashMap 基于哈希表(即散列表)的Map接口的实现,此实现提供所有可选的映射操作,并允许使用null值和null键. HashMap继承于AbstractMap,实现了Map.Cloneab ...
- jdk 8 HashMap源码解读
转自:https://www.cnblogs.com/little-fly/p/7344285.html 在原来的作者的基础上,增加了本人对源代码的一些解读. 如有侵权,请联系本人 这几天学习了Has ...
- HashMap源码解读
1.HashMap 1.6解读 a).put,get,遍历方式参看 http://www.cnblogs.com/skywang12345/p/3310835.html#a23 需要注意的是,1.7 ...
- HashMap源码解读(jdk1.8)
1.相关常量 默认初始化容量(大小) static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; 最大容量 static final int M ...
- HashMap 源码解读
HashMap在JDK1.7和1.8中有了很大的改变,空闲时间对HashMap做了一点点的研究. HashMap是一种数组和链表结合的数据结构,我们每次new一个HashMap时,都会构造出一个长度为 ...
- java集合之HashMap源码解读
源自:jdk1.8.0_121 HashMap继承自AbstractMap,实现了Map.Cloneable.Serializable. HashMap内部是由数组.链表.红黑树实现的 变量 // 默 ...
- 探索HashMap源码 一行一行解析 jdk1.7版本
今天我们来说一说,HashMap的源码到底是个什么? 面试大厂这方面一定会经常问到,很重要的.以jdk1.7 为标准 先带着大家过一遍 是由数组.链表组成 , 数组的优点是:每个元素有对应下标, ...
随机推荐
- mysql用户管理和pymysql
mysql用户管理 为了使不同的人员访问到对应身份的数据库资源,每个人都有不同的权限. mysql本质上是一款cs软件,它具备用户认证,那么如何实现呢?那就是写入文件,但是在mysql把文件称作表,只 ...
- HTTP协议响应篇
http响应的基本介绍 一个HTTP响应代表服务器向客户端回送的数据, 由三个部分构成 状态行[200 , 302 304, 403, 404, 500] 响应消息头 返回的实体内容 http响应状态 ...
- 4_9.springboot2.x之使用外置servlet容器原理解析
问题概述 嵌入式Servlet容器: 应用打成可执行的jar 优点:简单.便携: **缺点:**默认不支持JSP.优化定制比较复杂(使用定制器[ServerProperties.自定义WebServe ...
- 16-1-es5
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- java笔试之放苹果
题目描述:M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?(用K表示)5,1,1和1,5,1 是同一种分法. 输入:每个用例包含二个整数M和N.0<=m< ...
- UMP系统架构 Mnesia
- [模拟退火][UVA10228] A Star not a Tree?
好的,在h^ovny的安利下做了此题 模拟退火中的大水题,想当年联赛的时候都差点打了退火,正解貌似是三分套三分,我记得上一道三分套三分的题我就是退火水过去的... 貌似B班在讲退火这个大玄学... 这 ...
- win7 删除多余启动项的方法
win7已经没有像xp那么简单的boot.ini让我们修改了,取而代之的是bcdedit.现在就简单的说下bcdedit的常规应用吧.开始,运行,输入bcdedit /?可以看到帮助.简单的应用开始. ...
- Android开发 EditText按回车按键后出现 focus search returned a view that wasn't able to take focus! 错误
问题描述 将EditText这个View成为了ListView或者RecyclerView的item时,在按输入法的回车/下一步/next时会出现的 focus search returned a v ...
- MVVM test
示例代码 public class RegisterUserViewModel { public UserInfo userInfo { get; set; } public ICommand Cli ...