Java集合类源码问题总结----看到什么记什么

一.Hashmap

1.HashMap 最早出现在 JDK 1.2中,底层基于散列算法实现。HashMap 允许 null 键和 null 值,在计算哈键的哈希值时,null 键哈希值为 0。

2.HashMap 是非线程安全类

3.HashMap 则使用了拉链式的散列算法,并在 JDK 1.8 中引入了红黑树优化过长的链表

4.红黑树是一种自平衡二叉查找树,和AVL树类似,查找效率为Log2n,因为链表的查找效率是n,所以当Hashmap中元素较多时,采用红黑树的存储结构,能提高查找效率

5.默认情况下,HashMap 初始容量是16,负载因子为 0.75。这里并没有默认阈值,原因是阈值可由容量乘上负载因子计算而来

6.HashMap的容量指的是数组的容量

7.HashMap的容量为2的幂次,如果输入不是2的幂次,会转化为相差较近的2的幂次,为什么要规定为2的幂次?是因为能减小key的碰撞,提高链表的运行效率。

static int indexFor(int h, int length) {  
       return h & (length-1);  
   }  

上面的代码是计算元素放在哪个桶的坐标 他的结果是长度-1再和hash值进行与运算。

HashMap 中桶数组的大小 length 总是2的幂,此时,(n - 1) & hash 等价于hash值对 length 取余

Java集合类源码问题总结----看到什么记什么_第1张图片

/**
 * 计算键的 hash 值
 */
static final int hash(Object key) {
    int h;
    return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

上面的代码是计算hash值的方法,为什么要右移16位呢?
在 Java 中,hashCode 方法产生的 hash 是 int 类型,32 位宽。前16位为高位,后16位为低位,所以要右移16位。

这样做有两个好处:让高位数据参与运算,加强信息的随机性;另外,可以增加 hash 的复杂度。当我们覆写 hashCode 方法时,可能会写出分布性不佳的 hashCode 方法,进而导致 hash 的冲突率比较高。通过移位和异或运算,可以让 hash 变得更复杂

8.在计算key的插入位置index时,h&(length-1)和h%length得出的结果是一样的(返回h的低(length-1)位),但是位运算的速度会更快些


9.链表树化 TREEIFY

JDK 1.8 对 HashMap 实现进行了改进。最大的改进莫过于在引入了红黑树处理频繁的碰撞。当链表长度越来越长,对整个hashmap的 查找效率就会下降,这时将链表结构转为红黑树,就可以增加查找效率

链表树化需要满足两个条件:

  • 链表长度大于等于 TREEIFY_THRESHOLD 初始值为8
  • 桶数组容量大于等于 MIN_TREEIFY_CAPACITY 初始值为64

在桶容量比较小的时候,优先进行扩容,相比较链表树化效率更高。

二.Java集合类框图

主要是Collection类和Map类
Java集合类源码问题总结----看到什么记什么_第2张图片
Java集合类源码问题总结----看到什么记什么_第3张图片

你可能感兴趣的:(Java集合类源码学习笔记)