目录
一. 简介
HashMap是Java中常用的数据结构之一,它是基于哈希表
实现的,用于存储
和管理
键值对。HashMap内部是由一个Entry数组
和一个链表
组成的,数组用于存储
数据,链表用于解决哈希冲突
。HashMap会根据实际需要,动态地调整数组的长度,以保证高效的查找、插入和删除操作。
其主要特点包括:
- 高效性:HashMap内部采用哈希表实现,查找和插入操作的时间复杂度是O(1),具有高效性。
- 线程不安全:HashMap是非线程安全的,如果多个线程同时并发访问同一个HashMap对象,可能会出现数据不一致的情况。
- 支持null键和null值:HashMap允许键和值为null,但是需要注意,在使用时要特别小心,避免空指针异常。
- 无序性:HashMap中键值对的存储是无序的,与添加顺序无关。
总之,HashMap是一种高效的数据存储和查找结构,它在Java中得到广泛应用,特别是在缓存、索引、状态跟踪等领域。
二. 源码分析
基于JDK1.8版本
1. 成员变量属性
/**
* 默认初始容量(必须是2的幂次方)
* 指的是HashMap内部数组的大小
*/
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
/**
* 最大容量,如果任何一个带参数的构造函数隐式指定了更高的值,则使用该容量
* 必须是2的幂次方,最大不能超过1073741824
*/
static final int MAXIMUM_CAPACITY = 1 << 30;
/**
* 构造函数中未指定时使用的负载系数
* 指的是当HashMap内部数组的元素个数达到数组大小与负载因子的乘积时,会自动扩容
*/
static final float DEFAULT_LOAD_FACTOR = 0.75f;
/**
* 红黑树转成链表的长度阀值
* 当链表的长度小于6时,此时的红黑树会重新转换成链表结构
*/
static final int UNTREEIFY_THRESHOLD = 6;
/**
* 链表转化成红黑数的长度阈值
* 当数组的长度大于等于64,且链表的长度大于8时,链表转红黑树
*/
static final int TREEIFY_THRESHOLD = 8;
/**
* 将链表转话为红黑树的数组长度阀值
*/
static final int MIN_TREEIFY_CAPACITY = 64;
/**
* 哈希桶,可以理解就是数组
* 数组上存放的元素是Node<K,V>
*/
transient Node<K,V>[] table;
2. 构造函数
创建一个空的HashMap,默认初始化大小为16,负载因子为0.75
public HashMap() {
this.loadFactor = DEFAULT_LOAD_FACTOR;
}
创建一个指定初始容量的HashMap,默认负载因子为0.75
public HashMap(int initialCapacity) {
this(initialCapacity, DEFAULT_LOAD_FACTOR);
}
创建一个指定初始容量和负载因子的HashMap。
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);
this.loadFactor = loadFactor; //负载因子 0.75
//创建一个2的幂次容量大小的数组(对指定的容量值,取最大的2次幂)
this.threshold = tableSizeFor(initialCapacity);
}
创建一个包含指定Map中所有映射关系的新HashMap
public HashMap(Map<? extends K, ? extends V> m) {
this.loadFactor = DEFAULT_LOAD_FACTOR; //负载因子 0.75
putMapEntries(m, false);
}
3. put()
HashMap中的put方法用于将一个键值对(key-value)映射添加到HashMap中。其中,key表示要存储的键,value表示要存储的值。该方法的返回值为新添加的值
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}