HashMap源码1
jdk1.8之前是数组+链表的形式,后面会介绍jdk1.8对hashMap的改动:数组+链表+红黑树
transient是Java语言的关键字,用来表示一个域不是该对象串行化的一部分。
当一个对象被串行化的时候,transient型变量的值不包括在串行化的表示中,也就是说没法持久化。
因为读写Map是根据Object.hashcode()来确定从table[i]读/写
而Object.hashcode()是native方法, 不同的JVM里可能是不一样的
比如向HashMap存一个键值对entry, key为字符串"guowuxin", 在第一个java程序里, "guowuxin"的hashcode()为1, 存入table【】
在另一个JVM程序里, "guowuxin" 的hashcode()有可能就是2, 存入table【】
如果用默认的串行化(Entry[] table不用transient), 那么这个HashMap从第一个java程序里通过串行化导入第二个JVM环境之后, 其内存分布是一样的. 这就不对了.
HashMap现在的readObject和writeObject是把内容 输出/输入, 把HashMap重新生成出来.
所以HashMap自己实现了readObject和writeObject
另外因为 HashMap 中的存储数据的数组数据成员中,数组还有很多的空间没有被使用,没有被使用到的空间被序列化没有意义。所以需要手动使用 writeObject() 方法,只序列化实际存储元素的数组。

红黑树是O(logn),链表是O(n),大于等于7就转成红黑树,小于7时候O(longn)要大。


public class BB {
int i = ;
String s = "发大V";
AA dd() {
return new AA();
}
class AA{
AA(){}
void go() {
System.out.println(s);//直接使用外部类的属性
}
}
public static void main(String[] args) {
AA ss = new BB().dd();
ss.go();//发大V
}
}










我们知道java.util.HashMap不是线程安全的,因此如果在使用迭代器的过程中有其他线程修改了map,那么将抛出ConcurrentModificationException,这就是所谓fail-fast策略。
“重写equals时也要同时覆盖hashcode”:是根据key对象的hashcode判断在数组哪个位置,然后e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))
put(new Person(“haha”),“三三四四”) ;
get(new Person(“haha”))
public V get(Object key) {
Node<K,V> e;
return (e = getNode(hash(key), key)) == null ? null : e.value;
}
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
Get一个对象时候:对象相等,hashcode和equals方法相等。对象不相等,hashcode相等equals不能相等。hashcode不相等equals随意也不会冲突。
“重写equals时也要同时覆盖hashcode”是为了保证能够get到这个对象。
加载因子越大,填满的元素越多,好处是,空间利用率高了,但:冲突的机会加大了.链表长度会越来越长,查找效率降低。
加载因子越小,填满的元素越少,好处是:冲突的机会减小了,但:空间浪费多了.表中的数据将过于稀疏(很多空间还没用,就开始扩容了)冲突的机会越大,则查找的成本越高.
- 转为红黑树节点后,链表的结构还存在,通过next属性维持,红黑树节点在进行操作是都会维护链表的结构,并不是转为红黑树节点,链表结构就不存在了。
- 在红黑树上,叶子节点可能有next节点,因为红黑树的结构跟链表的结构是互不影响的,不会因为叶子节点就说该节点没有next节点了。
HashMap和Hashtable的区别:
HashMap允许key和value为null,Hashtable不允许。
HashMap的默认初始容量为16,Hashtable为11。
HashMap的扩容为原来的2倍,Hashtable的扩容为原来的2倍加1。
HashMap是非线程安全的,Hashtable是线程安全的。
HashMap的hash值重新计算过,Hashtable直接使用hashCode。
HashMap去掉了Hashtable中的contains方法。
HashMap继承自AbstractMap类,Hashtable继承自Dictionary类。
//java 8中的散列值优化函数
static final int hash(object key) {
int h;
return (key == null) ? : (h = key.hashcode()) ^ (h >>> ); //key.hashcode()为哈希算法,返回初始哈希值
}
大家都知道上面代码里的key.hashCode()函数调用的是key键值类型自带的哈希函数,返回int型散列值。 理论上散列值是一个int型,如果直接拿散列值作为下标访问HashMap主数组的话,考虑到2进制32位带符号的int表值范围从-2147483648到2147483648。前后加起来大概40亿的映射空间。只要哈希函数映射得比较均匀松散,一般应用是很难出现碰撞的。
右位移16位,正好是32bit的一半,自己的高半区和低半区做异或,就是为了混合原始哈希码的高位和低位,以此来加大低位的随机性。而且混合后的低位掺杂了高位的部分特征,这样高位的信息也被变相保留下来。
HashMap源码1的更多相关文章
- HashMap 源码解析
HashMap简介: HashMap在日常的开发中应用的非常之广泛,它是基于Hash表,实现了Map接口,以键值对(key-value)形式进行数据存储,HashMap在数据结构上使用的是数组+链表. ...
- HashMap源码分析
最近一直特别忙,好不容易闲下来了.准备把HashMap的知识总结一下,很久以前看过HashMap源码.一直想把集合类的知识都总结一下,加深自己的基础.我觉的java的集合类特别重要,能够深刻理解和应用 ...
- JAVA源码分析-HashMap源码分析(一)
一直以来,HashMap就是Java面试过程中的常客,不管是刚毕业的,还是工作了好多年的同学,在Java面试过程中,经常会被问到HashMap相关的一些问题,而且每次面试都被问到一些自己平时没有注意的 ...
- Java集合---HashMap源码剖析
一.HashMap概述二.HashMap的数据结构三.HashMap源码分析 1.关键属性 2.构造方法 3.存储数据 4.调整大小 5.数据读取 ...
- 【转】Java HashMap 源码解析(好文章)
.fluid-width-video-wrapper { width: 100%; position: relative; padding: 0; } .fluid-width-video-wra ...
- 【JAVA集合】HashMap源码分析(转载)
原文出处:http://www.cnblogs.com/chenpi/p/5280304.html 以下内容基于jdk1.7.0_79源码: 什么是HashMap 基于哈希表的一个Map接口实现,存储 ...
- HashMap源码解读(转)
http://www.360doc.com/content/10/1214/22/573136_78188909.shtml 最近朋友推荐的一个很好的工作,又是面了2轮没通过,已经是好几次朋友内推没过 ...
- HashMap源码剖析
HashMap源码剖析 无论是在平时的练习还是项目当中,HashMap用的是非常的广,真可谓无处不在.平时用的时候只知道HashMap是用来存储键值对的,却不知道它的底层是如何实现的. 一.HashM ...
- Java中HashMap源码分析
一.HashMap概述 HashMap基于哈希表的Map接口的实现.此实现提供所有可选的映射操作,并允许使用null值和null键.(除了不同步和允许使用null之外,HashMap类与Hashtab ...
- 转:【Java集合源码剖析】HashMap源码剖析
转载请注明出处:http://blog.csdn.net/ns_code/article/details/36034955 您好,我正在参加CSDN博文大赛,如果您喜欢我的文章,希望您能帮我投一票 ...
随机推荐
- APS.NET MVC + EF (14)---项目框架搭建
一:框架搭建 1:先创建Model. 2:创建数据访问接口层.IUserInfoDal 在该接口中定义了常见的方法CURD以及分页方法. public interface IUserInfoD ...
- vue开发相关问题以及解决方案
1.使用ref获取到dom元素,但是无法获取到dom元素的样式? 给div盒子加上<div ref="remove">, 在控制台打印为undefined. 此时我们打 ...
- Mac OS中的”任务管理器“
在开发使用过程中,经常需要通过任务管理器来查看进程的一些情况以及杀掉一些进程,Mac中也有类似于Windows的”资源管理器“. 启动台->其他 找到”活动监视器“ 活动监视器即是”任务管理器“ ...
- OKHttp和NumberProgressbar组建强大的Android版本更新功能
你们看过韩国电影<奇怪的她>不?女主角是不是超级漂亮的.......好啦,扯正事吧,先看看女神照片. 公司新项目用到了OKHttp网络框架,在下载文件这块都蒙圈啦,再查查资料就一个Reso ...
- Kotlin开发springboot项目(一)
Kotlin开发springboot项目(一) Kotlin语言与Xtend语言有很多相似之处 为什么会存在这么多JVM语言? 现存的语言提供了太过受限制的功能,要不就是功能太过繁杂,导致语言的臃肿和 ...
- 201871010126 王亚涛 《面向对象程序设计(java)》 第四周学习总结
项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.com/nwnu-daizh/p ...
- Java多线程编程核心技术-第7章-拾遗增补-读书笔记
第 7 章 拾遗增补 本章主要内容 线程组的使用. 如何切换线程状态. SimpleDataFormat 类与多线程的解决办法. 如何处理线程的异常. 7.1 线程的状态 线程对象在不同的运行时期有不 ...
- 小人大作战v0.02原型(单机)发布
运行环境,pc,windows 链接:https://pan.baidu.com/s/1X5XR0flRAVuinnydNyRNng 提取码:cp9q 复制这段内容后打开百度网盘手机App,操作更方便 ...
- woocommerce直接调取产品描述内容
最近一位客户想让woocommerce产品页直接调取描述内容,不想太多的tab切换,太复杂,这个蛮简单的,woocommerce是在wordpress基础开发的,产品也是post的一种类型,直接调用c ...
- 06-C#笔记-常量
1. 进制 前缀:0x 或 0X 表示十六进制,0 表示八进制,没有前缀则表示十进制. 后缀:可以是 U 或 L 的组合,其中,U 和 L 分别表示 unsigned 和 long.后缀可以是大写或者 ...