HashMap简介
HashMap是Java程序员使用频率最高的映射表集合类。它实现了Map接口,可以存储键值对,提供了快速查询功能。
HashMap特点
- 底层是哈希表结构,可以快速存取数据
- 键唯一,值可以重复。同一个键只能映射到一个值
- 元素存取顺序不确定,不保证顺序
- 默认初始容量(桶数)是16,加载因子是0.75
- 允许键值对都是null
HashMap源码解析
HashMap的核心成员变量有:
static final int DEFAULT_INITIAL_CAPACITY = 16;
static final float DEFAULT_LOAD_FACTOR = 0.75f;
transient Node<K,V>[] table; // 哈希桶数组
transient Set<Map.Entry<K,V>> entrySet;
主要的参数解析:
- initialCapacity - 初始容量,默认16
- loadFactor - 加载因子,默认0.75。超过这个比例就重新resize
- threshold - 扩容的阈值 = initialCapacity * loadFactor
重要方法解析:
- put - 将键值对添加到Map中
- get - 根据键获取值
- resize - 扩容方法
扩容机制:当链表长度超过8时会转换为红黑树;当桶数量超过阈值时 resize为原来的2倍。
HashMap避免碰撞的方法
HashMap使用哈希函数将键映射到不同的桶中,但仍可能发生碰撞。主要的优化手段有:
- 采用不容易冲突的好的哈希算法,比如已经优化的hashCode()方法
- 使用链地址法,将冲突元素组成链表放在同一个桶中
- 当链表长度超过8时,将链表转换为红黑树,降低查找复杂度
- 扩容,增加桶的数量,减少碰撞概率
HashSet简介
HashSet基于HashMap实现,它不存储重复元素,元素存放顺序不确定。
HashSet特点
- 唯一元素,不包含重复元素
- 基于HashMap实现,具有良好的查询和插入性能
- 元素存取顺序不确定,与添加顺序无关
- 允许包含一个null元素
HashSet源码解析
HashSet的核心实现就是基于HashMap:
public class HashSet<E> extends AbstractSet<E>
implements Set<E>, Cloneable, java.io.Serializable {
private transient HashMap<E,Object> map;
// Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object();
}
添加元素时,会将元素作为键放入底层的HashMap中,使用一个固定的Object对象作为值。
HashSet遍历方式
HashSet可以通过迭代器或者foreach的方式遍历:
// 迭代器遍历
Iterator iter = set.iterator();
while(iter.hasNext()){
// do something
}
// foreach遍历
for(Object obj : set){
// do something
}
总结
HashMap和HashSet都利用了哈希表作为底层结构,可以快速存取数据,但是代价是牺牲了元素的顺序。在Java集合框架中使用频率非常高,值得我们深入学习。
希望这篇博客对大家理解HashMap和HashSet有所帮助!如果文章中有任何错误,请不吝指正。