HashMap由数组和链表组成:数组为主体,链表是为了解决hash冲突而存在的。JDK1.8中若链表长度超过了8(含8),则链表转化为红黑树。jdk1.7链表从头部插入,jdk1.8链表从尾部插入。jdk1.8中entry替换为node。
HashMap继承AbstractMap并实现了Map接口:基于hash原理通过get()和put()存储和获取对象。
hash冲突:
如果根据hash函数算出来的hash值对应的数据位置不含链表(当前entry的next指向null),那么查找和添加很快,仅需一次寻址即可。反之比较慢需要遍历链表存在则覆盖更新,否则新增。查询时应需遍历链表通过key对象equals注意比较,所以hash算法十分重要,hah值冲突越少,链表越少,性能越好。
初始容量(initialCapacity):若不指定默认16,注意初始容量必须为2的幂次方,当构造函数传的值不为2的幂次方时hashMap会将其修改为最近的向上2的幂次方。比如传入9,自动更正为16。
加载因子(loadFactor):若不通过构造方法指定值默认为0.75;
扩容阈值(threshold):总容量*加载因子;当前容量大于该阈值时就会扩容。扩容的容量为当前的2倍。
哈希表(主干entry数组):HashMap中key和value存储都通过Entry介质来实现。table为Entry数组(jdk1.8Entry变更为Node)。hash值为数组下标。
为什么JDK1.8将Entry修改为Node类存储?
在JDK1.8的情况下,hash值冲突时,存储方式为链表或红黑树,Node类包含两个子类Entry和TreeNode用来支持存储两种类型。
什么是幂次方
通俗的说就是我们通常说的多少次方;比如平方为二次幂,立方为三次幂;幂的大小必须为整数,不能是小数和分数。
符号"^"用来表示次方,例如2的5次方为2^5。
什么是红黑树
自平衡的二叉查找数,自平衡的特性将HashMap中链表做出了优化。时间复杂度有O(n)降低到O(logn)。
什么是时间复杂度
时间复杂度是衡量算法好坏的一个重要指标。O(1) < O(logn) < O(n) < O(n^2)
是否线程安全
不是线程安全,可使用ConcurrentHashMap替代
HashMap的长度为什么必须为2的幂次方
为了HashMap存取更高效,尽量减少碰撞,将计算数组索引分布更均匀。索引值算法( n - 1) &hash
HashMap是否支持key或value为null
支持