HashMap
HashMap底层就是一个数组,而数组的每一项都是一个链表,当我们新建一个HashMap时就会初始化一个数组。HashMap有两个参数影响性能,分别是初始容量和加载因子。
HashMap寻址方式:对于一个新插入的数据或者需要读取的数据,HashMap需要根据key按照一个计算规则计算出Hash值并对我们的数组长度进行取模,取模结果作为数组的index,而取模的代价远远高于位运算的代价,因此HashMap的数组长度必须是2的N次方,将计算出的Hash值和2的N-1次方进行“与”运算,结果与取模操作是相同的。
HashMap并不要求用户在指定HashMap容量时必须传入一个2的N次方的整数,而是在初始化时根据传入的容量值计算出一个满足2的N次方的容量。
总所周知HashMap不是一个线程安全的,主要体现在执行resize方法时可能会产生死循环,当HashMap的size超过他的容量*负载因子时,就需要对HashMap扩容,具体方法是创建一个新的原来容量的两倍的数组(保证新的容量仍然是2的N次方,从而保证上述的寻址方式仍然适用),同时把原来的数组重新插入到新的数组中,这一过程并不保证线程安全,而且在多线程并发调用时可能会产生死循环。
上面是单线程下reHash的扩容步骤。
在多线程情况下:
ConcurrentHashMap
数据结构:
使用了红黑树来提高性能。