HashMap源代码解析
HashMap原理剖析
之前有看过别人的HashMap源代码的分析,今天尝试自己来分析一波,纯属个人愚见。听一些老的程序员说过,当别人跟你说用某样技术到项目中去,而你按照别人的想法实现了的时候,你只能是一个码农,当你自己会想到用一样东西到你的实际开发中的时候,你是一个普通的程序员,当你不仅能想到用某样技术到项目中去,而且深深的熟悉这项技术的底层实现,那就是一个有内功的程序员了。
HashMap,哈希表,基于哈希算法实现的一个java集合。起初使用这个哈希表的时候,感觉非常的不习惯,主要是容易和其他的几种哈希表搞混,就当时的理解来说,哪个哈希表的键不能为空,哪个哈希表的值可以为空等等,觉得这些东西记住了就感觉自己非常的牛逼了。但是随着学习的进一步深入,总会有疑问,哈希表到底是如何实现的?那就按照api的方法来一个一个解释。
构造方法:
1.空参数的构造方法
public HashMap() {
//初始化加载因子,等于默认的加载因子0.75
this.loadFactor = DEFAULT_LOAD_FACTOR;
//最大容量为初始化容量乘以加载因子
threshold = (int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR);
//初始化一个长度为16的entry数组,也就是存放键值对的数组
table = new Entry[DEFAULT_INITIAL_CAPACITY];
//调用init方法
init();
}
2.初始化容量的构造方法
public HashMap(int initialCapacity) {
//调用两个参数的构造方法,初始化容量和默认加载因子
this(initialCapacity, DEFAULT_LOAD_FACTOR);
}
3.初始化容器和初始化加载因子的构造方法
public HashMap(int initialCapacity, float loadFactor) {
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal initial capacity: " +
initialCapacity);
if (initialCapacity > MAXIMUM_CAPACITY)
initialCapacity = MAXIMUM_CAPACITY;
if (loadFactor <= 0 || Float.isNaN(loadFactor))
throw new IllegalArgumentException("Illegal load factor: " +
loadFactor);
int capacity = 1;
while (capacity < initialCapacity)
capacity <<= 1;
this.loadFactor = loadFactor;
threshold = (int)(capacity * loadFactor);
table = new Entry[capacity];
init();
}
4.Map集合作为参数的构造方法
public HashMap(Map<? extends K, ? extends V> m) {
//调用初始化加载因子和初始化容量两个参数的构造方法
this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1,
DEFAULT_INITIAL_CAPACITY), DEFAULT_LOAD_FACTOR);
//将参数Map中的key-value对放入新创建的map集合中
putAllForCreate(m);
}
存放键值对的方法:
public V put(K key, V value) {
//如果key为空,则调用放入null key的方法,占用entry数组的一个位置
if (key == null)
return putForNullKey(value);
//根据key值计算出hash码值
int hash = hash(key.hashCode());
//并根据哈希码的值计算出该key-value在entry数组中的存放位置
int i = indexFor(hash, table.length);
//根据索引直接定位到那个元素并且从那个元素开始遍历
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
modCount++;//修改次数加1
addEntry(hash, key, value, i);//将key-value对添加进入entry数组
return null;
}
HashMap源代码解析的更多相关文章
- Android xUtils3源代码解析之网络模块
本文已授权微信公众号<非著名程序猿>原创首发,转载请务必注明出处. xUtils3源代码解析系列 一. Android xUtils3源代码解析之网络模块 二. Android xUtil ...
- android7.x Launcher3源代码解析(3)---workspace和allapps载入流程
Launcher系列目录: 一.android7.x Launcher3源代码解析(1)-启动流程 二.android7.x Launcher3源代码解析(2)-框架结构 三.android7.x L ...
- 使用具体解释及源代码解析Android中的Adapter、BaseAdapter、ArrayAdapter、SimpleAdapter和SimpleCursorAdapter
Adapter相当于一个数据源,能够给AdapterView提供数据.并依据数据创建相应的UI.能够通过调用AdapterView的setAdapter方法使得AdapterView将Adapter作 ...
- Spring源代码解析
Spring源代码解析(一):IOC容器:http://www.iteye.com/topic/86339 Spring源代码解析(二):IoC容器在Web容器中的启动:http://www.itey ...
- java集合框架之java HashMap代码解析
java集合框架之java HashMap代码解析 文章Java集合框架综述后,具体集合类的代码,首先以既熟悉又陌生的HashMap开始. 源自http://www.codeceo.com/arti ...
- Arrays.sort源代码解析
Java Arrays.sort源代码解析 Java Arrays中提供了对所有类型的排序.其中主要分为Primitive(8种基本类型)和Object两大类. 基本类型:采用调优的快速排序: 对象类 ...
- Spring源代码解析(收藏)
Spring源代码解析(收藏) Spring源代码解析(一):IOC容器:http://www.iteye.com/topic/86339 Spring源代码解析(二):IoC容器在Web容器中的 ...
- volley源代码解析(七)--终于目的之Response<T>
在上篇文章中,我们终于通过网络,获取到了HttpResponse对象 HttpResponse是android包里面的一个类.然后为了更高的扩展性,我们在BasicNetwork类里面看到.Volle ...
- Cocos2d-x源代码解析(1)——地图模块(3)
接上一章<Cocos2d-x源代码解析(1)--地图模块(2)> 通过前面两章的分析,我们能够知道cocos将tmx的信息结构化到 CCTMXMapInfo.CCTMXTilesetInf ...
随机推荐
- 数组相关方法积累(vue\ag等特别常用)
改变原数组的: shift:将第一个元素删除并且返回删除元素,空即为undefined unshift:向数组开头添加元素,并返回新的长度 pop:删除最后一个并返回删除的元素 push:向数组末尾添 ...
- zabbix使用(自定义监控、自动报警)
自定义监控(制作模板) zabbix自带模板Template OS Linux (Template App Zabbix Agent)提供CPU.内存.磁盘.网卡等常规监控,只要新加主机关联此模板,就 ...
- .NET中的集合-ArrayList2
数组特点:类型同统一,长度固定 集合常用操作 添加 遍历 移除 ArrayList可变长度数组,使用类似于数组 属性:capacity(集合中可以容纳元素的个数,翻倍增长)count(集合中实际存放的 ...
- [转]深入Java单例模式
文章从 https://blog.51cto.com/devbean/203501 转载 问题 : doble-check 实现的单例模式有什么缺点 线程安全的单例写法应该是怎么样的 概述 在G ...
- js 千分位符号 正则方法
function toThousands(num) { return (num || 0).toString().replace(/(\d)(?=(?:\d{3})+$)/g, '$1,');}
- 十、获取异步线程返回值Callable
一.简介 异步线程的实现接口Runnable是无法获得返回结果的,而另一个接口Callable可以返回结果.并通过如Future等方式来获取异步结果. 二.代码示例 import java.util. ...
- memcached 细究(二)
{ CentOS ping命令 分布式部署服务器时用到ping命令 #ping -c 4 192.168.16.1 //ping4次后结束. } 使用telnet 查看memcached 运行状态 ...
- final关键字的特点
1.这个关键字是一个修饰符,可以修饰类,方法,变量. 2.被final修饰的类是一个最终类,不可以被继承. 3.被final修饰的方法是一个最终方法,不可以被覆盖. 4.被final修饰的变量是一个常 ...
- javaweb项目中绝对路径的写法理解
Tomcat的默认访问路径为http://localhost:8080,后需添加项目路径. 请求转发,是转发到本项目中的其他文件,所以在默认访问路径中添加了本项目的项目路径,故可以省略项目名称: re ...
- springcloud 集成kafka问题记录,发消息报错:ERROR o.s.kafka.support.LoggingProducerListener - Exception thrown when sending a message with key='null' and payload='{-1,
在springcloud集成kafka,发送消息时报错: 2018-08-15 16:01:34.159 [http-nio-8081-exec-1] INFO org.apache.kafka.c ...