![](https://img-blog.csdnimg.cn/20200613022303407.jpeg?x-oss-process=image/resize,m_fixed,h_224,w_224)
从头开始学Java源码
本专栏系统地梳理了Java源码的核心知识点,并对其进行讲解和演示。
lwen.steven
学好Java,为公司“添砖加瓦”!
展开
-
17.Java8相较于Java7在集合模块的改动
1.新增forEach方法List、Set、Map在Java8版本中都增加了forEach方法,方法的入参是Consumer,Consumer 是一个函数式接口,可以简单理解成允许一个入参,但没有返回值的函数式接口。下面以ArrayList的forEach源码为例,来分析该方法是如何实现的 ,具体源码如下。public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess原创 2020-10-16 16:01:51 · 3253 阅读 · 0 评论 -
16.集合源码对实际工作的帮助
1.线程安全集合都是非线程安全的,这里说的非线程安全指的是集合类作为共享变量,被多线程读写的时候是不安全的,如果要实现线程安全的集合,可以使用Collections类中以synchronized开头的相关方法, Collections实现了List、Set、Map对应的线程安全方法。下面以synchronizedList为例,来分析Collections是如何实现线程安全的,具体源码如下所示。public class Collections { //mutex为需要锁住的对象 final Objec原创 2020-10-16 16:01:13 · 88 阅读 · 0 评论 -
15.CopyOnWriteArrayList和ConcurrentHashMap源码面试题集锦
1.CopyOnWriteArrayList和ArrayList相比有哪些相同点和不同点?答:相同点是底层的数据结构都是数组,提供出来的API都是对数组进行的操作。不同点是后者是线程安全的,在多线程环境下使用,无需加锁。2.CopyOnWriteArrayList通过哪些手段实现了线程安全?答:主要通过以下三点保证了线程安全。第一,数组容器被volatile关键字修饰,保证了数组内存地址被任意线程修改后,都会通知到其他线程。第二,对数组的所有修改,都进行了加锁操作,保证了同一时刻,只能有一个线程对数组原创 2020-10-16 15:57:14 · 124 阅读 · 0 评论 -
14.ConcurrentHashMap源码解析
1.架构ConcurrentHashMap的底层数据结构和方法的实现细节与HashMap大体一致,但两者在类结构上却没有任何关联,看ConcurrentHashMap源码,会发现很多方法的代码和HashMap很相似,那就会存在一个问题,为什么不继承HashMap呢?继承的确是个好办法,但尴尬的是,ConcurrentHashMap都是在方法中间进行一些加锁操作,也就是说加锁把方法切割了,继承就很难解决这个问题。ConcurrentHashMap和HashMap两者的相同之处主要有两点。一是数组、链表结构原创 2020-10-16 15:56:24 · 107 阅读 · 0 评论 -
13.CopyOnWriteArrayList源码解析
1.简介在ArrayList的类注释上,JDK就有相应提示,如果要把ArrayList作为共享变量的话,是线程不安全的,推荐开发者自己加锁或者使用Collections的synchronizedList方法,其实JDK还提供了另外一种线程安全的List,叫做 CopyOnWriteArrayList,这个List具有以下特征。是线程安全的,多线程环境下可以直接使用,无需加锁。通过锁 + 数组拷贝 + volatile关键字保证了线程安全。每次数组操作,都会把数组拷贝一份,在新数组上进行操作,操作成原创 2020-10-16 15:55:24 · 91 阅读 · 0 评论 -
12.Set源码面试题集锦
1.TreeSet在什么场景下使用?答:一般在需要把元素进行排序的场景下使用,使用时,元素最好实现Comparable接口,这样方便底层的TreeMap根据key进行排序。2.追问,如果想实现根据key的新增顺序进行遍历,应该怎么办?答:要按照key的新增顺序进行遍历,首先想到的是LinkedHashMap,而LinkedHashSet正好是基于LinkedHashMap实现的,所以可以选择使用LinkedHashSet。3.追问,如果想对key进行去重,应该怎么办?答:首先想到的是TreeSet原创 2020-10-15 15:15:07 · 98 阅读 · 0 评论 -
11.TreeSet源码解析
1.简介TreeSet大致的结构和HashSet相似,底层组合的是TreeMap,所以继承了TreeMap能够排序的功能,也可以按照key的排序进行顺序迭代。2.复用思路一TreeSet在复用TreeMap的功能时,主要有两种实现思路。复用思路一是底层直接使用HashMap提供的能力,如TreeSet的add方法,其源码如下所示。public class TreeSet<E> extends AbstractSet<E> implements NavigableSet<原创 2020-10-15 15:14:37 · 150 阅读 · 0 评论 -
10.HashSet源码解析
1.类注释HashSet的底层实现基于HashMap,因此迭代时不能保证按照插入顺序进行迭代。HashSet的add、remove、contanins、size等方法的耗时性能,不会随着数据量的增加而增加,原因跟HashMap底层的数组数据结构有关,不管数据量多大,不考虑hash冲突的情况下,时间复杂度都是O(1)。HashSet是线程不安全的,如果需要安全请自行加锁,或者使用Collections的synchronizedSet方法。迭代过程中,如果数据结构被改变,会快速失败,会抛出 Concu原创 2020-10-15 15:00:18 · 194 阅读 · 0 评论 -
9.Map源码面试题集锦
1.HashMap底层数据结构是什么?答:HashMap底层数据结构是数组、链表和红黑树的组合,数组的主要作用是方便快速查找,时间复杂度是O(1),默认大小是16,数组的下标索引是通过key的hashcode计算的。数组元素叫做Node,当多个key的hashcode一致但key值不同时,单个Node会转化成链表,链表的查询复杂度是O(n),当链表的长度大于等于8并且数组的大小超过64时,链表会转化成红黑树,红黑树的查询复杂度是O(log(n)),简单来说,最坏的查询次数相当于红黑树的最大深度。2.Ha原创 2020-10-15 14:33:43 · 110 阅读 · 0 评论 -
8.LinkedHashMap源码解析
1.数据结构LinkedHashMap继承自HashMap,底层数据结构和HashMap的结构一样并且拥有HashMap的所有特性。不同的是,LinkedHashMap新增了"按照插入顺序访问"和"删除最少访问元素策略"。源码public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V>{ //链表头 transient LinkedHashMap.Entry<K,V>原创 2020-10-15 14:33:12 · 107 阅读 · 0 评论 -
7.TreeMap源码解析
1.数据结构TreeMap的底层数据结构是红黑树,和HashMap的红黑树结构一样。不同的是,TreeMap利用红黑树左节点小,右节点大的性质,根据key进行排序,使每个元素能够插入到红黑树的适当位置,维护了key的大小关系,适用于key需要排序的场景。因为底层使用的是平衡红黑树的结构,所以containsKey、get、put、remove等方法的时间复杂度都是log(n)。源码public class TreeMap<K,V> extends AbstractMap<K,V>原创 2020-10-15 14:32:39 · 94 阅读 · 0 评论 -
6.HashMap源码解析
1.数据结构如上图所示,HashMap底层的数据结构主要是数组 + 链表 + 红黑树。其中当链表的长度大于等于8时,链表会转化成红黑树,当红黑树的大小小于等于6时,红黑树会转化成链表。图中左边竖着的是HashMap的数组结构,数组的元素可以是单个Node,也可以是链表或红黑树,比如数组下标索引为2的位置就是一个链表,下标索引为9的位置对应的是红黑树。源码public class HashMap<K,V> extends AbstractMap<K,V> implements原创 2020-10-15 14:31:50 · 129 阅读 · 0 评论 -
5.List源码面试题集锦
1.新建一个ArrayList,现在add一个值,此时数组的大小是多少?下一次扩容前最大可用大小是多少?答:此处数组的大小是1,下一次扩容前最大可用大小是10。因为ArrayList无参构造器初始化时,默认大小是空数组,第一次添加元素的时候进行扩容,大小是默认的10。2.如果连续往ArrayList里面新增值,增加到第11个的时候,数组的大小是多少?答:此时的数组大小是15。这里考查的是扩容公式,当增加到第11个元素的时候,此时希望数组的大小为11,但实际上数组的最大容量只有10,此时便需要扩容,扩容原创 2020-10-14 00:45:45 · 164 阅读 · 0 评论 -
4.LinkedList源码解析
1.数据结构LinkedList底层数据结构是一个双向链表,整体结构如上图所示,链表中的每个节点都可以向前或者向后追溯。链表的每个节点都被称为Node,Node有prev和next属性,分别代表前一个节点和后一个节点的位置。first是双向链表的头节点,它的前一个节点是null,last是双向链表的尾节点,它的后一个节点也是null。当链表中没有数据时,first和last是同一个节点,前后指向都是null。因为是个双向链表,只要机器内存足够强大,是没有大小限制的。源码private sta原创 2020-10-14 00:45:34 · 101 阅读 · 0 评论 -
3.ArrayList源码解析
1.数据结构ArrayList的数据结构是一个数组,如上图所示,图中展示的是一个长度为10的数组,从1开始计数,index表示数组的下标,从0开始计数,elementData表示数组元素。除此之外,源码中还有三个基本概念。源码public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable {原创 2020-10-14 00:45:13 · 120 阅读 · 0 评论 -
2.Integer源码解析
1.取值范围和基本数据类型源码public final class Integer extends Number implements Comparable<Integer> { //该值用于定义Integer取值的最小值 @Native public static final int MIN_VALUE = 0x80000000; //该值用于定义Integer取值的最大值 @Native public static final int MAX原创 2020-10-14 00:45:03 · 177 阅读 · 2 评论 -
1.String源码解析
1.不变性这里说的不变性指的是类值一旦被初始化,就不能再被改变了,如果被修改,将会是新的类,如程序1-1所示。//程序1-1public class App { public static void main(String[] args) { String str = "hello steven"; System.out.println(str); str = "hello mike"; System.out.println(s原创 2020-10-14 00:44:50 · 162 阅读 · 0 评论 -
从头开始学Java源码
基础篇1.String源码解析2.Integer源码解析集合篇3.ArrayList源码解析4.LinkedList源码解析5.List源码面试题集锦6.HashMap源码解析7.TreeMap源码解析8.LinkedHashMap源码解析9.Map源码面试题集锦10.HashSet源码解析11.TreeSet源码解析12.Set源码面试题集锦13.CopyOnWriteArrayList源码解析14.ConcurrentHashMap源码解析15.CopyOnWriteAr原创 2020-10-14 00:44:39 · 112 阅读 · 0 评论