HashMap和HashSet笔记(内部结构&使用场景)

《java编程的逻辑》读书笔记

HashMap

  1. 主要实例变量:

transient Entry[] talbe = (Entry[]) EMPTY_TABLE; // 称为哈希表或哈系桶,其中每个元素指向一个单向链表,链表中每个节点表示一个键值对。
transient int size; // 键值对个数
int threshold; // 阙值,当键值对个数大于等于threshold时考虑进行扩展
final float loadFactor; // 负载因子,表示整体上table被占用的成都,是一个浮点数,默认0.75,可以通过构造方法修改

threshold:
2. 一般而言,threshold等于table.length乘以loadFactor。如果:table.length = 16, loadFactor = 0.75,则threshold为12。

  1. 扩展策略类似ArrayList,添加第一个元素时,默认分配大小:16,不过并不是size大于16在进行扩展,下册什么时候扩展与threshold有关
  2. HashMap的put方法,先计算key的hash值,然后把hash值进行一些位运算(为了随机和均匀性),拿到key在table中的位置;(不同的hash值进行位运算后位置可能相同,相同位置的元素组成单向链表,链表每个节点表示一个键值对)
    table[i]指向一个单向链表

小结:

  1. 根据键保存和获取值的效率都很高,为O(1),每个单向链表往往只有一个或少数几个节点,根据hash值就可以直接快速定位;
  2. HashMap中的键值对 没有顺序,因为hash值是随机的

如果经常需要根据键值存取值,而且不要求顺序,那么HashMap就是理想的选择。如果要保持添加顺序,可以使用HashMap的子类LinkedHashMap。Map还有一个TreeMap实现类,可以排序。

HashMap不是线程安全的,HashTable是Java最早实现的容器类之一,实现了Map接口,实现原理与HashMap类似,但是没有特别的优化,它内部通过synchronized实现了线程安全。在HashMap中,键和值都可以为null,而在Hashtable中不可以。在不需要并发安全的场景中,推荐使用HashMap。在高并发的场景中,推荐使用ConcurrentHashMap。

HashSet

HashSet内部使用HashMap实现的,它内部有一个HashMap实例变量
private transient HashMap map;
HashSet相当于只有键,值都是相同的固定值,这个值定义为:
private static final Object PRESENT = new Object();
比如add方法:

public boolean add(E e){
	return map.put(e,PRESENT) == null;
}

小结:

  1. 没有重复元素
  2. 可以高效的添加、删除元素、判断元素是否存在,效率都为O(1)
  3. 没有顺序。

HashSet可以方便高效地实现去重、集合运算等功能。如果要保持添加的顺序,可以使用HashSet的一个子类,LinkedHashSet。Set还有一个重要的 实现类TreeSet,它可以排序。

你可能感兴趣的:(java小公举)