Map接口
1.和Collection接口是java.util包下的两大接口
一次保存两个关系是key == value的对象
2.常用方法
put(K key,V value)
get(K key)
public Set<K> keySet()
public Collection<V> values()
public Set<Map,Entry<K,V>> entrySet();//将Map集合,变为Set集合。
3.HashMap、HashTable、TreeMap、ConcurrentHashMap。
HashMap子类源码分析,因为HashMap设计与实现是个非常高频的面试题
HashMap内部实现基本点分析
1.可以看成是数组和链表结合形成的复合结构。
2.在首次使用时被初始化
3.putVal函数里,如果表格是null,resize方法负责初始化他
resize方法兼顾两个职责,创建出事存储表格,或者在容量不满足需求的时候,进 行扩容
面试官经常追问resize()方法,源码实现
门限值等于(负载因子)*(容量)
当元素个数超过门限值,则调整Map大小
扩容后,需要将老的数组中的元素放到新数组中,这是扩容的一个主要开销来源。
容量、负载因子、树化
1.容量和负载系数决定了可用桶的数量
2.负载因子*容量>元素数量
所以预设的容量需要满足,大于预估元素数量/负载因子,同时它是2的幂。
如果没有特殊需求,不要轻易更改,建议不要超过0.75的数值
树化
final void treeifyBin(Node<K,V>[] tab, int hash) {
int n, index; Node<K,V> e;
if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY)
resize();
else if ((e = tab[index = (n - 1) & hash]) != null) {
// 树化改造逻辑
}
1.当 bin 的数量大于 TREEIFY_THRESHOLD 时:
如果容量小于 MIN_TREEIFY_CAPACITY,只会进行简单的扩容。
如果容量大于 MIN_TREEIFY_CAPACITY ,则会进行树化改造。
为什么要进行树化,因为如果一个哈希对象冲突,都被放置在一个桶里,则会形成一个链表,由于链表是线性的,会严重影响存取性能。