JDK 1.5 HashMap 源代码读解
HashMap
基于哈希表的 Map 接口的实现。
此实现提供所有可选的映射操作,并允许使用 null 值和 null 键。
(除了不同步和允许使用 null 之外,HashMap 类与 Hashtable 大致相同。)
此类不保证映射的顺序,特别是它不保证该顺序恒久不变。
(from JDK DOC)
缺省的 Map大小是 16. (这里要求必须是 2 的幂数,为什么一定是 2的幂数(16,32,64,128...下边有解释).
static final int DEFAULT_INITIAL_CAPACITY = 16;
缺省的比例因子是 0.75
static final float DEFAULT_LOAD_FACTOR = 0.75f;
长度必须总是 2 的 幂数。
保存 K,V 对象的数组
transient Entry[] table;
/**
* The next size value at which to resize (capacity * load factor).
* @serial
*/
重设 Entry[] table 的阀值( = capacity * load factor)
int threshold;
当前比例因子
final float loadFactor;
记录修改次数
transient volatile int modCount;
/**
* Constructs an empty <tt>HashMap</tt> with the specified initial
* capacity and load factor.
*
* @param initialCapacity The initial capacity.
* @param loadFactor The load factor.
* @throws IllegalArgumentException if the initial capacity is negative
* or the load factor is nonpositive.
*/
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);
// Find a power of 2 >= initialCapacity
int capacity = 1;
while (capacity < initialCapacity)
capacity <<= 1;
this.loadFactor = loadFactor;
threshold = (int)(capacity * loadFactor); loadFactor 默认是 0.75. 所以 threshold 默认是 12
table = new Entry[capacity]; 按照给定的大小初化 Entry 数组。(默认情况下是 16 )
init();
}
看了下边这几行代码就能看出来 HashMap是怎么支持 null 做为 Key了。
static final Object NULL_KEY = new Object();
static <T> T maskNull(T key) {
return key == null ? (T)NULL_KEY : key;
}
static <T> T unmaskNull(T key) {
return (key == NULL_KEY ? null : key);
}
HashMap 对key 值的 hash 算法。
Object 类使用的 对象的 内部地址 提供 hashCode.
String 使用一个算法提供hashCode。(算法:s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1])
当然这样一种算法是不能完全保证 得到的hashCode是唯一的。
String s1 = "结算";
String s2 = "罚款";
两个对象的hashcode是相同的(1038116);
经过hash之后是-423929781.
这个函数的算法我就看不大懂了。还有高人指教了。
static int hash(Object x) {
int h = x.hashCode();
h += ~(h << 9);
h ^= (h >>> 14);
h += (h << 4);
h ^= (h >>> 10);
return h;
}
根据hashCode值 值和 当前 Entry数组的长度计算 该数据应该在数组中的索引值
因为这里的算法 所以 capacity 大小必须为 2 的幂数。
举例,默认值是 16 , 其减1是 15, 二进制是 00001111 .
h 是一个特殊的 hash值。 与 0x0F进行 & 操作当然结果应该在 0x0F以内了。
但这里必须保证 length -1 全为 1. 否则话某些位可能永远是 0,那么Entry数组
的一个范围可能永远也不会被用到。
这里没使用取余计算应该出于效率考虑的吧。
static int indexFor(int h, int length) {
return h & (length-1);
}
public V get(Object key) {
Object k = maskNull(key); //检查是否是null Key
int hash = hash(k); //计算hash
int i = indexFor(hash, table.length); //计算索引
Entry<K,V> e = table[i]; //取得Entry对象
while (true) { //循环查找链上 对象
if (e == null)
转载于:https://www.cnblogs.com/hcmsxy/archive/2008/07/18/2164062.html
JDK 1.5 HashMap 源代码读解相关推荐
- HashMap源代码详解
HashMap类声明 HashMap类声明如下: public class HashMap<K,V> extends AbstractMap<K,V> implements M ...
- 【Java基础】HashMap原理详解
[Java基础]HashMap原理详解 HashMap的实现 1. 数组 2.线性链表 3.红黑树 3.1概述 3.2性质 4.HashMap扩容死锁 5. BATJ一线大厂技术栈 HashMap的实 ...
- HashMap原理详解(基于jdk1.8)
HashMap原理详解(基于jdk1.8) HashMap原理详解,有兴趣的同学可以看下.有错误的地方也希望大佬们能指点下. HashMap的内部存储是一个数组(bucket),数组的元素Node实现 ...
- 查看源代码Source not found及在eclipse中配置jdk的src.zip源代码
查看源代码Source not found及在eclipse中配置jdk的src.zip源代码 https://blog.csdn.net/tuke_tuke/article/details/5154 ...
- Spring框架学习day_02:组件扫描 / 注解内部读解 / 组件扫描中配置作用域和生命周期 / 解耦 / 自动装配(两种方式) / 读取文件
1. 组件扫描 首先,必须让Spring扫描组件所在的包,并且,组件类的声明之前必须添加@Component注解! 其实,除了@Component注解以外,还可以使用以下注解实现同样的效果: @Con ...
- Atitit.jdk java8的语法特性详解 attilax 总结
Atitit.jdk java8的语法特性详解 attilax 总结 1.1. 类型推断这个特别有趣的.鲜为人知的特性1 2. Lambda1 2.1. 内部迭代意味着改由Java类库来进行迭代,而不 ...
- kbengine 源代码读
第一时间更新地址:kbengine bbs 以下摘自百度百科: """ KBEngine是一款开源的游戏服务端引擎,使用简单的约定协议就能够使客户端与服务端进行交互, 使 ...
- 《四书五经》之大学全文、注释及读解 好东西啊
http://www.douban.com/group/topic/2058726/[原文] 大学之道(1),在明明德(2),在亲民(3),在止于至善. 知止(4)而后有定:定而后能静:静而后能 ...
- emule中节点加入Kad网络过程(源代码详解)【对原文部分改进】
from: http://blog.csdn.net/chenbuaa/article/details/2301656 emule中节点加入Kad网络过程(源代码详解) 程序启动: EmuleDlg. ...
- java JDK安装与环境配置详解(超超超级详细)
点击以下链接获取详细图文教程! java JDK安装与环境配置详解 https://v.xiumi.us/board/v5/3QTAV/112689421
最新文章
- 2020年一季度中小微企业收入平均下降69.5%
- jenkins~管道Pipeline里使用公用类库
- 科大星云诗社动态20210808
- 怎样对流媒体进行压力测试_暖气片怎样安装效果好?暖气片正确的安装,采暖效果更好!...
- java多个mapreduce_一个简单的MapReduce示例(多个MapReduce任务处理)
- 基于模板的文字识别结果结构化处理技术
- mysql timestamp类型比较_MySQL timestamp 类型比较的测试
- 光电雷达智能跟踪平台
- 第二周函数-的基本格式:
- 【2019杭电多校第六场1011=HDU6644】11 Dimensions(dp+思维)
- js,如何把省份简称转换成省份全称
- java抓包WIFI包_教你手机应用如何通过wifi上网抓包
- 介绍几款知名的工作流系统软件
- 记录一个非常好用的模拟器:夜神模拟器
- 安兔兔html5测试跑分榜,2021年最新安兔兔手机性能跑分排行榜
- Bitmap、CBitmap、HBITMAP以及BITMAP的相互转换
- 人工智能 | ShowMeAI资讯日报 #2022.06.13
- [设计模式] 调停者模式(Mediator Pattern)
- 面试题19/leetcode10:正则表达式匹配 C++
- ERC721: Non-fungible Token Standard
热门文章
- ERROR 1045 (28000): Access denied for user 'admin'@'localhost' (using password: YES)
- Log_Analysis_using_OSSEC.md
- HDU 4859 海岸线(最大流最小割)
- 我怎么感觉js快无敌了~
- 使用finalize/dispose 模式提高GC性能(翻译)
- jquery ajax get 数组参数
- 使用多线程提高Rest服务性能
- Solr进阶之Solr综合文本相似度的多因素权重排序实现
- NFS, web,负载均衡,Nginx yum 源码安装
- ELK——Logstash 2.2 mutate 插件【翻译+实践】