HashMap源码学习

时间:2022-07-22
本文章向大家介绍HashMap源码学习,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

首先实现map的子类:HashMap、HashTable、TreeMap、LinkedHashMap。

这几个类中HashMap与HashTable的区别:

线程上:HashMap是线程不安全的,而HashTable是安全的。key、value的支持:HashMap的key、balue可以为空,而HashTable是key、value不可以为空的。底层数据结构:HashMap采用数组+链表+红黑树,当链表的长度>=8的时候会考虑是否转成红黑树,而HashTable则没有。初始化容量上:HashTable的初始化容量是11,同时扩容变为原来的2n+1,HashMap的初始化容量是16,同时扩容扩容成原来的2倍。而当给定初始化容量时,HashTable是直接给定初始化容量,而HashMap是将给定的初始化容量变成2的次幂。

jdk7和jdk8之间,jdk8引入了红黑树,同时jdk7中的transform( )方法变成了resize( )方法。什么是红黑树,同时数组什么时候会加入链表,链表和数组满足什么条件时,链表会变成红黑树,什么时候红黑树又会变成链表。同时如果给定初始化容量,给成怎样会才合理。

1.HashMap相关变量

//默认初始化容量2^4 =16,做左移位运算
static final int DEFAULT_INITIAL_CAPACITY=1<<4;
//最大容量 2^30
static final int MAXIMUM_CAPACITY = 1 << 30;
//默认加载因子 0.75
static final float DEFAULT_LOAD_FACTOR = 0.75f;
//需要变成红黑树的链表阀值 8
static final int TREEIFY_THRESHOLD = 8;
//将红黑树变成链表的阀值 6
static final int UNTREEIFY_THRESHOLD = 6;
//变成红黑树除了满足链表达到8,而且数组需要
//达到64,最小转成红黑树的数组长度64
static final int MIN_TREEIFY_CAPACITY = 64;
//数组,又称为bucket,桶,2的次幂
transient Node<K,V>[] table;
//entrySet:k、v对的集合
transient Set<Map.Entry<K,V>> entrySet;
//map的长度
transient int size;
//修改次数
transient int modCount;
//阀值  threshold = capacity*loadFactor
int threshold;
//加载因子
final float loadFactor;

2.构造函数

public HashMap(int initialCapacity,

3.方法

put方法

//如果元素属于树节点,则进行红黑树的判断,执

扩容操作

else {//否者没有进行初始容量,则

remove操作

return(e=removeNode(hash(key),key,null,false,

get操作

return (e = getNode(hash(key), key))

从里面可以收获到的一些结论:

HashMap的源码较多,且综合了数组、链表、红黑树的操作,因此不管是get还是remove还是get都需要考虑到三张数据结构的操作。同时红黑树是一种平衡二叉树,节点是黑色或者红色的,根节点为黑色的,每个红色节点的两个叶子节点都是黑色的,从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。同时当key相同时,会出现冲突,此时就需要解决hash冲突,此时就将其放入到链表中。而当链表的长度>=8时,数组长度>=64时,则变成红黑树。给定初始化容量时,给定元素个数/加载因子为最佳初始化容量,可以在源码找到这个代码。