源码可是个好东西,好的源码就像一件艺术品,从源码中我们不但可以学习代码设计思维和风格,还能了解一些常用类的数据结构,看一次源码比背100次原理要来的容易得多,如果觉得源码难读,就先从简单的入手吧!
重点源码:
包装类、集合、反射、线程(线程池)、spring、String/StringBuffer/StringBuilder、Object类
高级java开发工程师需要了解一下源码:
(1)List、Map、Set实现类的源代码
(2)ReentrantLock、AQS的源代码
(3)AtomicInteger的实现原理,主要能说清楚CAS机制并且AtomicInteger是如何利用CAS机制实现的
(4)线程池的实现原理
(5)Object类中的方法以及每个方法的作用
源码学习与介绍:
1.String类
String类是final的,不允许被继承
String类的内部就是维护了一个char数组;(底层是char数组)
常用的length,charAt方法,这两个方法,实际上就是在操作char数组
String类中的hashCode计算方法还是比较简单的,就是以31为权,每一位为字符的ASCII值进行运算,用自然溢出来等效取模。
2.ArrayList类
ArrayList维护了一个Object数组(底层),默认容量是10
private static final int DEFAULT_CAPACITY = 10;
第 11 次添加元素,此时 size+1 = 11,而数组长度是10,这时候创建一个长度为10+10*0.5 = 15 的数组(扩容1.5倍),然后将原数组元素引用拷贝到新数组。并将第 11 次添加的元素赋值到新数组下标为10的位置。
3.LinkedList类
LinkedList底层使用的双向链表结构,有一个头结点和一个尾结点,双向链表意味着我们可以从头开始正向遍历,或者是从尾开始逆向遍历,并且可以针对头部和尾部进行相应的操作。
add函数用于向LinkedList中添加一个元素,并且添加到链表尾部。
值得注意的是LinkedList可以作为双端队列使用,这也是队列结构在Java中一种实现
4.HashMap类
在JDK1.8之前,HashMap采用数组+链表实现,即使用链表处理冲突,同一hash值的节点都存储在一个链表里。但是当位于一个桶中的元素较多,即hash值相等的元素较多时,通过key值依次查找的效率较低。而JDK1.8中,HashMap采用数组+链表+红黑树实现,当链表长度超过阈值(8)时,将链表转换为红黑树,这样大大减少了查找时间。
// 默认的初始容量是16
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;
备注:HashMap的容量为什么是2的n次方:当容量为2的n次方时,hash & (length - 1) == hash % length ,于是就在源码中做了优化,通过 hash & (length - 1) 来替代取模运算,而前提就是容量必须为2的n次方。
- 提高操作运算效率(位运算效率 > 取模运算效率)
- 减少碰撞,数据均匀分布,提高HashMap查询效率
jdk1.8的HashMap数据结构
// 当桶(bucket)上的结点数大于这个值时会转成红黑树
static final int TREEIFY_THRESHOLD = 8;
// 当桶(bucket)上的结点数小于这个值时树转链表
static final int UNTREEIFY_THRESHOLD = 6;
// 桶中结构转化为红黑树对应的table的最小大小
static final int MIN_TREEIFY_CAPACITY = 64;
5.HashSet类
构造方法
public HashSet() {
map = new HashMap<>();
}
//HashSet集合中的内容是通过 HashMap 数据结构来存储的
private transient HashMap<E,Object> map;
//向HashSet中添加数据,数据在上面的 map 结构是作为 key 存在的,而value统一都是 PRESENT
private static final Object PRESENT = new Object();
第一个定义一个 HashMap,作为实现 HashSet 的数据结构;第二个 PRESENT 对象,因为前面讲过 HashMap 是作为键值对 key-value 进行存储的,而 HashSet 不是键值对,那么选择 HashMap 作为实现,其原理就是存储在 HashSet 中的数据 作为 Map 的 key,而 Map 的value 统一为 PRESENT(下面介绍具体实现时会了解)。
其他:TreeMap和TreeSet,基于红黑树实现的,TreeMap 是由红黑树实现的有序的 key-value 集合。
6.StringBuffer/StringBuilder
都是继承了AbstractStringBuilder类
本质上还是char数组
他们之前的区别就在于StringBuffer在重写父类的方法时,都加了synchronized关键字。注:当创建StringBuffer和StringBuilder时,默认长度是 16
觉得不错的小伙伴可以右上角点个赞或关注哟!