1:首先下载openjdk(http://pan.baidu.com/s/1dFMZXg1),把源码导入eclipse,以便看到jdk源码
Windows-Preferences-Java-Installed JREs,选中相应的jdk,Edit-选中rt.jre,点击Source Attachment,在弹出的菜单中选中单选按钮External location,把下载好的源码导进来.(如图)
2:HashMap概述
HashMap是基于哈希表的Map接口的非同步实现,允许使用null值和null键,但不保障顺序不变
3:HashMap的数据结构
HashMap实际是一个 链表散列 的数据结构,即数组和链表的结合体
如图:HashMap底层是一个数组结构,数组的每一项又是一个链表.
Map<Object,Object> hashMap = new HashMap<>();//其中默认加载因子是0.75f,默认初始容量16,table是一个长度为16的数组.
4:HashMap的存取实现
public V put(K key, V value) {
//当key为null时,调用putForNullKey(value);把value放入数组第一个位置
if (key == null)
return putForNullKey(value);
//根据key的hashCode重新计算hash值
int hash = hash(key.hashCode());
//搜索制定的hash值在table中的索引
int i = indexFor(hash, table.length);
//如果i索引处的entry不为null,通过循环不断遍历e的下一个元素
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;
}
}
//如果i索引处的Entry为null,表明此处还没有Entry
modCount++;
//将K,V增加到i所引处
addEntry(hash, key, value, i);
return null;
}
从上面的源代码中可以看出:当我们往HashMap 中put 元素的时候,先根据key 的hashCode 重新计算hash 值,根据hash 值得到这个元素在数组中的位置(即下标),如
果数组该位置上已经存放有其他元素了,那么在这个位置上的元素将以链表的形式存放,新加入的放在链头,最先加入的放在链尾。如果数组该位置上没有元素,就直接将该元素放到此数组中的该位置上。
addEntry(hash, key, value, i)方法根据计算出的hash 值,将key-value 对放在数组table的i 索引处.addEntry 是 HashMap 提供的一个包访问权限的方法,代码如下:
void addEntry(int hash, K key, V value, int bucketIndex) {
// 获取指定 bucketIndex 索引处的 Entry
Entry<K,V> e = table[bucketIndex];
// 将新创建的 Entry 放入 bucketIndex 索引处,并让新的 Entry 指向原来的 Entry
table[bucketIndex] = new Entry<K,V>(hash, key, value, e);
// 如果 Map 中的 key-value 对的数量超过了极限
if (size++ >= threshold)
// 把 table 对象的长度扩充到原来的2 倍。
resize(2 * table.length);
}
当系统决定存储HashMap 中的key-value 对时,完全没有考虑Entry 中的value,仅仅只是根据key 来计算并决定每个Entry 的存储位置。我们完全可以把 Map 集合中的 value 当
成 key 的附属,当系统决定了 key 的存储位置之后,value 随之保存在那里即可。
hash(int h)方法根据key 的hashCode 重新计算一次散列。此算法加入了高位计算,防止低位不变,高位变化时,造成的hash 冲突。
static int hash(int h) {
h ^= (h >>> 20) ^ (h >>> 12);
return h ^ (h >>> 7) ^ (h >>> 4);
}
------------------------------------------------------未完待续--------------------------------------
牛人的理解:http://blog.csdn.net/tuke_tuke/article/details/51588156
①访问修饰符为什么是16
java底层是C语言开发的,C语言底层是汇编(汇编使用的是16进制),汇编来源于机器语言
②hashMap(数组+链表+红黑树)
③hashmap的扩容是怎么操作的,扩容后元素是如何保障均匀分布的