diff --git a/README.md b/README.md
index 7cf58b258f0..786e0ccf6d9 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-👉 如果你不知道该学习什么的话,请看 [Java 学习线路图是怎样的?]( https://zhuanlan.zhihu.com/p/379041500) (原创不易,欢迎点赞),这是 2021 最新最完善的 Java 学习路线!另外,我整理了一份各个技术的学习路线,需要的小伙伴[加我微信](#联系我)备注“**Github-学习路线**”即可!
+👉 如果你不知道该学习什么的话,请看 [Java 学习线路图是怎样的?]( https://zhuanlan.zhihu.com/p/379041500) (原创不易,欢迎点赞),这是 2021 最新最完善的 Java 学习路线!另外,[我的朋友整理了一份消息队列常见面试题,需要的小伙伴可以点击领取!](http://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&mid=100025985&idx=1&sn=681af486050fabbeea27fa1c3bec5d65&chksm=4ea1e94a79d6605c72f280b5268100c6e96c6ab1dc9a0178b33e25a72ff5f4eac3dcb56fa44f#rd)
👉 推荐 [在线阅读](https://snailclimb.gitee.io/javaguide) (Github 访问速度比较慢可能会导致部分图片无法刷新出来)
@@ -44,7 +44,7 @@
### 基础
-**知识点/面试题:**(必看:+1: )
+**知识点/面试题** : (必看:+1: )
1. **[Java 基础知识](docs/java/basis/Java基础知识.md)**
2. **[Java 基础知识疑难点/易错点](docs/java/basis/Java基础知识疑难点.md)**
@@ -71,11 +71,11 @@
**重要知识点详解:**
-2. **线程池**:[Java 线程池学习总结](./docs/java/multi-thread/java线程池学习总结.md)、[拿来即用的线程池最佳实践](./docs/java/multi-thread/拿来即用的线程池最佳实践.md)
-4. [ ThreadLocal 关键字解析](docs/java/multi-thread/万字详解ThreadLocal关键字.md)
-5. [并发容器总结](docs/java/multi-thread/并发容器总结.md)
-6. [JUC 中的 Atomic 原子类总结](docs/java/multi-thread/Atomic原子类总结.md)
-7. [AQS 原理以及 AQS 同步组件总结](docs/java/multi-thread/AQS原理以及AQS同步组件总结.md)
+1. **线程池**:[Java 线程池学习总结](./docs/java/multi-thread/java线程池学习总结.md)、[拿来即用的线程池最佳实践](./docs/java/multi-thread/拿来即用的线程池最佳实践.md)
+2. [ ThreadLocal 关键字解析](docs/java/multi-thread/万字详解ThreadLocal关键字.md)
+3. [并发容器总结](docs/java/multi-thread/并发容器总结.md)
+4. [JUC 中的 Atomic 原子类总结](docs/java/multi-thread/Atomic原子类总结.md)
+5. [AQS 原理以及 AQS 同步组件总结](docs/java/multi-thread/AQS原理以及AQS同步组件总结.md)
### JVM (必看 :+1:)
@@ -93,7 +93,12 @@ JVM 这部分内容主要参考 [JVM 虚拟机规范-Java8 ](https://docs.oracle
### 新特性
1. **Java 8** :[Java 8 新特性总结](docs/java/new-features/Java8新特性总结.md)、[Java8常用新特性总结](docs/java/new-features/java8-common-new-features.md) 、[Java 8 学习资源推荐](docs/java/new-features/Java8教程推荐.md)、[Java8 forEach 指南](docs/java/new-features/Java8foreach指南.md)
-2. **Java9~Java14** : [一文带你看遍 JDK9~14 的重要新特性!](./docs/java/new-features/一文带你看遍JDK9到14的重要新特性.md)
+2. **Java9~Java15** : [一文带你看遍 JDK9~15 的重要新特性!](./docs/java/new-features/java新特性总结.md)
+
+### 小技巧
+
+1. [JAD 反编译](docs/java/tips/JAD反编译tricks.md)
+2. [手把手教你定位常见 Java 性能问题](./docs/java/tips/手把手教你定位常见Java性能问题.md)
## 计算机基础
@@ -101,22 +106,27 @@ JVM 这部分内容主要参考 [JVM 虚拟机规范-Java8 ](https://docs.oracle
### 操作系统
-1. [操作系统常见问题总结!](docs/operating-system/basis.md)
-2. [后端程序员必备的 Linux 基础知识](docs/operating-system/linux.md)
-3. [Shell 编程入门](docs/operating-system/Shell.md)
+1. [操作系统常见问题总结!](docs/cs-basics/operating-system/basis.md)
+2. [后端程序员必备的 Linux 基础知识总结](docs/cs-basics/operating-system/linux.md)
+3. [Shell 编程入门](docs/cs-basics/operating-system/Shell.md)
### 网络
-1. [计算机网络常见面试题](docs/network/计算机网络.md)
-2. [计算机网络基础知识总结](docs/network/计算机网络知识总结.md)
+1. [计算机网络常见面试题](docs/cs-basics/network/计算机网络.md)
+2. [计算机网络基础知识总结](docs/cs-basics/network/计算机网络知识总结.md)
### 数据结构
-- **图解数据结构:**
- 1. [线性数据结构 :数组、链表、栈、队列](docs/dataStructures-algorithms/data-structure/线性数据结构.md)
- 2. [图](docs/dataStructures-algorithms/data-structure/图.md)
- 3. [堆](docs/dataStructures-algorithms/data-structure/堆.md)
-- [不了解布隆过滤器?一文给你整的明明白白!](docs/dataStructures-algorithms/data-structure/bloom-filter.md)
+**图解数据结构:**
+
+1. [线性数据结构 :数组、链表、栈、队列](docs/cs-basics/data-structure/线性数据结构.md)
+2. [图](docs/cs-basics/data-structure/图.md)
+3. [堆](docs/cs-basics/data-structure/堆.md)
+4. [树](docs/cs-basics/data-structure/树.md) :重点关注[红黑树](docs/cs-basics/data-structure/红黑树.md)、B-,B+,B*树、LSM树
+
+其他常用数据结构 :
+
+1. [布隆过滤器](docs/cs-basics/data-structure/bloom-filter.md)
### 算法
@@ -125,11 +135,13 @@ JVM 这部分内容主要参考 [JVM 虚拟机规范-Java8 ](https://docs.oracle
- [算法学习书籍+资源推荐](https://www.zhihu.com/question/323359308/answer/1545320858) 。
- [如何刷Leetcode?](https://www.zhihu.com/question/31092580/answer/1534887374)
-**常见算法问题总结:**
+**常见算法问题总结** :
+
+- [几道常见的字符串算法题总结 ](docs/cs-basics/algorithms/几道常见的字符串算法题.md)
+- [几道常见的链表算法题总结 ](docs/cs-basics/algorithms/几道常见的链表算法题.md)
+- [剑指 offer 部分编程题](docs/cs-basics/algorithms/剑指offer部分编程题.md)
-- [几道常见的字符串算法题总结 ](docs/dataStructures-algorithms/几道常见的字符串算法题.md)
-- [几道常见的链表算法题总结 ](docs/dataStructures-algorithms/几道常见的链表算法题.md)
-- [剑指 offer 部分编程题](docs/dataStructures-algorithms/剑指offer部分编程题.md)
+另外,[GeeksforGeeks]( https://www.geeksforgeeks.org/fundamentals-of-algorithms/) 这个网站总结了常见的算法 ,比较全面系统。
## 数据库
@@ -147,9 +159,10 @@ JVM 这部分内容主要参考 [JVM 虚拟机规范-Java8 ](https://docs.oracle
1. [MySQL数据库索引总结](docs/database/mysql/MySQL数据库索引.md)
2. [事务隔离级别(图文详解)](docs/database/mysql/事务隔离级别(图文详解).md)
-3. [InnoDB存储引擎对MVCC的实现](docs/database/mysql/InnoDB对MVCC的实现.md)
-4. [一条 SQL 语句在 MySQL 中如何执行的](docs/database/mysql/一条sql语句在mysql中如何执行的.md)
-5. [关于数据库中如何存储时间的一点思考](docs/database/mysql/关于数据库存储时间的一点思考.md)
+3. [MySQL三大日志(binlog、redo log和undo log)详解](docs/database/mysql/MySQL三大日志(binlog、redo log和undo log).md)
+4. [InnoDB存储引擎对MVCC的实现](docs/database/mysql/InnoDB对MVCC的实现.md)
+5. [一条 SQL 语句在 MySQL 中如何执行的](docs/database/mysql/一条sql语句在mysql中如何执行的.md)
+6. [关于数据库中如何存储时间的一点思考](docs/database/mysql/关于数据库存储时间的一点思考.md)
### Redis
@@ -353,7 +366,6 @@ Dubbo 是一款国产的 RPC 框架,由阿里开源。相关阅读:
## 工具
-1. **Java** :[JAD 反编译](docs/java/JAD反编译tricks.md)、[手把手教你定位常见 Java 性能问题](./docs/java/手把手教你定位常见Java性能问题.md)
2. **Git** :[Git 入门](docs/tools/Git.md)
3. **Github** : [Github小技巧](docs/tools/Github技巧.md)
4. **Docker** : [Docker 基本概念解读](docs/tools/Docker.md) 、[Docker从入门到上手干事](docs/tools/Docker从入门到实战.md)
@@ -377,7 +389,8 @@ Dubbo 是一款国产的 RPC 框架,由阿里开源。相关阅读:
### 待办
-- [ ] 数据结构总结重构
+- [ ] 计算机网络知识点完善
+- [ ] 分布式常见理论和算法总结完善
### 捐赠支持
diff --git "a/docs/dataStructures-algorithms/\345\207\240\351\201\223\345\270\270\350\247\201\347\232\204\345\255\227\347\254\246\344\270\262\347\256\227\346\263\225\351\242\230.md" "b/docs/cs-basics/algorithms/\345\207\240\351\201\223\345\270\270\350\247\201\347\232\204\345\255\227\347\254\246\344\270\262\347\256\227\346\263\225\351\242\230.md"
similarity index 100%
rename from "docs/dataStructures-algorithms/\345\207\240\351\201\223\345\270\270\350\247\201\347\232\204\345\255\227\347\254\246\344\270\262\347\256\227\346\263\225\351\242\230.md"
rename to "docs/cs-basics/algorithms/\345\207\240\351\201\223\345\270\270\350\247\201\347\232\204\345\255\227\347\254\246\344\270\262\347\256\227\346\263\225\351\242\230.md"
diff --git "a/docs/dataStructures-algorithms/\345\207\240\351\201\223\345\270\270\350\247\201\347\232\204\351\223\276\350\241\250\347\256\227\346\263\225\351\242\230.md" "b/docs/cs-basics/algorithms/\345\207\240\351\201\223\345\270\270\350\247\201\347\232\204\351\223\276\350\241\250\347\256\227\346\263\225\351\242\230.md"
similarity index 100%
rename from "docs/dataStructures-algorithms/\345\207\240\351\201\223\345\270\270\350\247\201\347\232\204\351\223\276\350\241\250\347\256\227\346\263\225\351\242\230.md"
rename to "docs/cs-basics/algorithms/\345\207\240\351\201\223\345\270\270\350\247\201\347\232\204\351\223\276\350\241\250\347\256\227\346\263\225\351\242\230.md"
diff --git "a/docs/dataStructures-algorithms/\345\211\221\346\214\207offer\351\203\250\345\210\206\347\274\226\347\250\213\351\242\230.md" "b/docs/cs-basics/algorithms/\345\211\221\346\214\207offer\351\203\250\345\210\206\347\274\226\347\250\213\351\242\230.md"
similarity index 100%
rename from "docs/dataStructures-algorithms/\345\211\221\346\214\207offer\351\203\250\345\210\206\347\274\226\347\250\213\351\242\230.md"
rename to "docs/cs-basics/algorithms/\345\211\221\346\214\207offer\351\203\250\345\210\206\347\274\226\347\250\213\351\242\230.md"
diff --git a/docs/dataStructures-algorithms/data-structure/bloom-filter.md b/docs/cs-basics/data-structure/bloom-filter.md
similarity index 74%
rename from docs/dataStructures-algorithms/data-structure/bloom-filter.md
rename to docs/cs-basics/data-structure/bloom-filter.md
index bfb7efe7f03..9b5afd6d5c5 100644
--- a/docs/dataStructures-algorithms/data-structure/bloom-filter.md
+++ b/docs/cs-basics/data-structure/bloom-filter.md
@@ -6,18 +6,18 @@
2. 布隆过滤器的原理介绍。
3. 布隆过滤器使用场景。
4. 通过 Java 编程手动实现布隆过滤器。
-5. 利用Google开源的Guava中自带的布隆过滤器。
+5. 利用 Google 开源的 Guava 中自带的布隆过滤器。
6. Redis 中的布隆过滤器。
### 1.什么是布隆过滤器?
首先,我们需要了解布隆过滤器的概念。
-布隆过滤器(Bloom Filter)是一个叫做 Bloom 的老哥于1970年提出的。我们可以把它看作由二进制向量(或者说位数组)和一系列随机映射函数(哈希函数)两部分组成的数据结构。相比于我们平时常用的的 List、Map 、Set 等数据结构,它占用空间更少并且效率更高,但是缺点是其返回的结果是概率性的,而不是非常准确的。理论情况下添加到集合中的元素越多,误报的可能性就越大。并且,存放在布隆过滤器的数据不容易删除。
+布隆过滤器(Bloom Filter)是一个叫做 Bloom 的老哥于 1970 年提出的。我们可以把它看作由二进制向量(或者说位数组)和一系列随机映射函数(哈希函数)两部分组成的数据结构。相比于我们平时常用的的 List、Map 、Set 等数据结构,它占用空间更少并且效率更高,但是缺点是其返回的结果是概率性的,而不是非常准确的。理论情况下添加到集合中的元素越多,误报的可能性就越大。并且,存放在布隆过滤器的数据不容易删除。

-位数组中的每个元素都只占用 1 bit ,并且每个元素只能是 0 或者 1。这样申请一个 100w 个元素的位数组只占用 1000000Bit / 8 = 125000 Byte = 125000/1024 kb ≈ 122kb 的空间。
+位数组中的每个元素都只占用 1 bit ,并且每个元素只能是 0 或者 1。这样申请一个 100w 个元素的位数组只占用 1000000Bit / 8 = 125000 Byte = 125000/1024 kb ≈ 122kb 的空间。
总结:**一个名叫 Bloom 的人提出了一种来检索元素是否在给定大集合中的数据结构,这种数据结构是高效且性能很好的,但缺点是具有一定的错误识别率和删除难度。并且,理论情况下,添加到集合中的元素越多,误报的可能性就越大。**
@@ -35,11 +35,9 @@
举个简单的例子:
-
-

-如图所示,当字符串存储要加入到布隆过滤器中时,该字符串首先由多个哈希函数生成不同的哈希值,然后将对应的位数组的下标设置为 1(当位数组初始化时,所有位置均为0)。当第二次存储相同字符串时,因为先前的对应位置已设置为 1,所以很容易知道此值已经存在(去重非常方便)。
+如图所示,当字符串存储要加入到布隆过滤器中时,该字符串首先由多个哈希函数生成不同的哈希值,然后将对应的位数组的下标设置为 1(当位数组初始化时,所有位置均为 0)。当第二次存储相同字符串时,因为先前的对应位置已设置为 1,所以很容易知道此值已经存在(去重非常方便)。
如果我们需要判断某个字符串是否在布隆过滤器中时,只需要对给定字符串再次进行相同的哈希计算,得到值之后判断位数组中的每个元素是否都为 1,如果值都为 1,那么说明这个值在布隆过滤器中,如果存在一个值不为 1,说明该元素不在布隆过滤器中。
@@ -49,7 +47,7 @@
### 3.布隆过滤器使用场景
-1. 判断给定数据是否存在:比如判断一个数字是否存在于包含大量数字的数字集中(数字集很大,5亿以上!)、 防止缓存穿透(判断请求的数据是否有效避免直接绕过缓存请求数据库)等等、邮箱的垃圾邮件过滤、黑名单功能等等。
+1. 判断给定数据是否存在:比如判断一个数字是否存在于包含大量数字的数字集中(数字集很大,5 亿以上!)、 防止缓存穿透(判断请求的数据是否有效避免直接绕过缓存请求数据库)等等、邮箱的垃圾邮件过滤、黑名单功能等等。
2. 去重:比如爬给定网址的时候对已经爬取过的 URL 去重。
### 4.通过 Java 编程手动实现布隆过滤器
@@ -206,7 +204,7 @@ true
实际使用如下:
-我们创建了一个最多存放 最多 1500个整数的布隆过滤器,并且我们可以容忍误判的概率为百分之(0.01)
+我们创建了一个最多存放 最多 1500 个整数的布隆过滤器,并且我们可以容忍误判的概率为百分之(0.01)
```java
// 创建布隆过滤器对象
@@ -224,7 +222,7 @@ System.out.println(filter.mightContain(1));
System.out.println(filter.mightContain(2));
```
-在我们的示例中,当`mightContain()` 方法返回 *true* 时,我们可以99%确定该元素在过滤器中,当过滤器返回 *false* 时,我们可以100%确定该元素不存在于过滤器中。
+在我们的示例中,当`mightContain()` 方法返回 _true_ 时,我们可以 99%确定该元素在过滤器中,当过滤器返回 _false_ 时,我们可以 100%确定该元素不存在于过滤器中。
**Guava 提供的布隆过滤器的实现还是很不错的(想要详细了解的可以看一下它的源码实现),但是它有一个重大的缺陷就是只能单机使用(另外,容量扩展也不容易),而现在互联网一般都是分布式的场景。为了解决这个问题,我们就需要用到 Redis 中的布隆过滤器了。**
@@ -234,17 +232,17 @@ System.out.println(filter.mightContain(2));
Redis v4.0 之后有了 Module(模块/插件) 功能,Redis Modules 让 Redis 可以使用外部模块扩展其功能 。布隆过滤器就是其中的 Module。详情可以查看 Redis 官方对 Redis Modules 的介绍 :https://redis.io/modules
-另外,官网推荐了一个 RedisBloom 作为 Redis 布隆过滤器的 Module,地址:https://github.com/RedisBloom/RedisBloom。其他还有:
+另外,官网推荐了一个 RedisBloom 作为 Redis 布隆过滤器的 Module,地址:https://github.com/RedisBloom/RedisBloom。其他还有:
- redis-lua-scaling-bloom-filter(lua 脚本实现):https://github.com/erikdubbelboer/redis-lua-scaling-bloom-filter
-- pyreBloom(Python中的快速Redis 布隆过滤器) :https://github.com/seomoz/pyreBloom
+- pyreBloom(Python 中的快速 Redis 布隆过滤器) :https://github.com/seomoz/pyreBloom
- ......
RedisBloom 提供了多种语言的客户端支持,包括:Python、Java、JavaScript 和 PHP。
-#### 6.2 使用Docker安装
+#### 6.2 使用 Docker 安装
-如果我们需要体验 Redis 中的布隆过滤器非常简单,通过 Docker 就可以了!我们直接在 Google 搜索 **docker redis bloomfilter** 然后在排除广告的第一条搜素结果就找到了我们想要的答案(这是我平常解决问题的一种方式,分享一下),具体地址:https://hub.docker.com/r/redislabs/rebloom/ (介绍的很详细 )。
+如果我们需要体验 Redis 中的布隆过滤器非常简单,通过 Docker 就可以了!我们直接在 Google 搜索 **docker redis bloomfilter** 然后在排除广告的第一条搜素结果就找到了我们想要的答案(这是我平常解决问题的一种方式,分享一下),具体地址:https://hub.docker.com/r/redislabs/rebloom/ (介绍的很详细 )。
**具体操作如下:**
@@ -252,15 +250,15 @@ RedisBloom 提供了多种语言的客户端支持,包括:Python、Java、Ja
➜ ~ docker run -p 6379:6379 --name redis-redisbloom redislabs/rebloom:latest
➜ ~ docker exec -it redis-redisbloom bash
root@21396d02c252:/data# redis-cli
-127.0.0.1:6379>
+127.0.0.1:6379>
```
-#### 6.3常用命令一览
+#### 6.3 常用命令一览
-> 注意: key : 布隆过滤器的名称,item : 添加的元素。
+> 注意: key : 布隆过滤器的名称,item : 添加的元素。
-1. **`BF.ADD `**:将元素添加到布隆过滤器中,如果该过滤器尚不存在,则创建该过滤器。格式:`BF.ADD {key} {item}`。
-2. **`BF.MADD `** : 将一个或多个元素添加到“布隆过滤器”中,并创建一个尚不存在的过滤器。该命令的操作方式`BF.ADD`与之相同,只不过它允许多个输入并返回多个值。格式:`BF.MADD {key} {item} [item ...]` 。
+1. **`BF.ADD`**:将元素添加到布隆过滤器中,如果该过滤器尚不存在,则创建该过滤器。格式:`BF.ADD {key} {item}`。
+2. **`BF.MADD`** : 将一个或多个元素添加到“布隆过滤器”中,并创建一个尚不存在的过滤器。该命令的操作方式`BF.ADD`与之相同,只不过它允许多个输入并返回多个值。格式:`BF.MADD {key} {item} [item ...]` 。
3. **`BF.EXISTS` ** : 确定元素是否在布隆过滤器中存在。格式:`BF.EXISTS {key} {item}`。
4. **`BF.MEXISTS`** : 确定一个或者多个元素是否在布隆过滤器中存在格式:`BF.MEXISTS {key} {item} [item ...]`。
@@ -268,19 +266,19 @@ root@21396d02c252:/data# redis-cli
这个命令的格式如下:
-`BF.RESERVE {key} {error_rate} {capacity} [EXPANSION expansion] `。
+`BF.RESERVE {key} {error_rate} {capacity} [EXPANSION expansion]`。
下面简单介绍一下每个参数的具体含义:
1. key:布隆过滤器的名称
-2. error_rate :误报的期望概率。这应该是介于0到1之间的十进制值。例如,对于期望的误报率0.1%(1000中为1),error_rate应该设置为0.001。该数字越接近零,则每个项目的内存消耗越大,并且每个操作的CPU使用率越高。
-3. capacity: 过滤器的容量。当实际存储的元素个数超过这个值之后,性能将开始下降。实际的降级将取决于超出限制的程度。随着过滤器元素数量呈指数增长,性能将线性下降。
+2. error_rate :误报的期望概率。这应该是介于 0 到 1 之间的十进制值。例如,对于期望的误报率 0.1%(1000 中为 1),error_rate 应该设置为 0.001。该数字越接近零,则每个项目的内存消耗越大,并且每个操作的 CPU 使用率越高。
+3. capacity: 过滤器的容量。当实际存储的元素个数超过这个值之后,性能将开始下降。实际的降级将取决于超出限制的程度。随着过滤器元素数量呈指数增长,性能将线性下降。
可选参数:
-- expansion:如果创建了一个新的子过滤器,则其大小将是当前过滤器的大小乘以`expansion`。默认扩展值为2。这意味着每个后续子过滤器将是前一个子过滤器的两倍。
+- expansion:如果创建了一个新的子过滤器,则其大小将是当前过滤器的大小乘以`expansion`。默认扩展值为 2。这意味着每个后续子过滤器将是前一个子过滤器的两倍。
-#### 6.4实际使用
+#### 6.4 实际使用
```shell
127.0.0.1:6379> BF.ADD myFilter java
@@ -294,4 +292,3 @@ root@21396d02c252:/data# redis-cli
127.0.0.1:6379> BF.EXISTS myFilter github
(integer) 0
```
-
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\233\276.png" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\345\233\276.png"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\233\276.png"
rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\345\233\276.png"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2421.drawio" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2421.drawio"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2421.drawio"
rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2421.drawio"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2421.png" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2421.png"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2421.png"
rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2421.png"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2422.drawio" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2422.drawio"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2422.drawio"
rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2422.drawio"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2422.png" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2422.png"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2422.png"
rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2422.png"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2423.drawio" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2423.drawio"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2423.drawio"
rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2423.drawio"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2423.png" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2423.png"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2423.png"
rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2423.png"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2424.drawio" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2424.drawio"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2424.drawio"
rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2424.drawio"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2424.png" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2424.png"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2424.png"
rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2424.png"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2425.drawio" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2425.drawio"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2425.drawio"
rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2425.drawio"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2425.png" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2425.png"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2425.png"
rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2425.png"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2426.drawio" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2426.drawio"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2426.drawio"
rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2426.drawio"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2426.png" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2426.png"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2426.png"
rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2426.png"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\242\345\233\276\347\244\272.drawio" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\242\345\233\276\347\244\272.drawio"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\242\345\233\276\347\244\272.drawio"
rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\242\345\233\276\347\244\272.drawio"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\242\345\233\276\347\244\272.png" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\242\345\233\276\347\244\272.png"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\242\345\233\276\347\244\272.png"
rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\242\345\233\276\347\244\272.png"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\227\240\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\347\237\251\351\230\265\345\255\230\345\202\250.drawio" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\346\227\240\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\347\237\251\351\230\265\345\255\230\345\202\250.drawio"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\227\240\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\347\237\251\351\230\265\345\255\230\345\202\250.drawio"
rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\346\227\240\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\347\237\251\351\230\265\345\255\230\345\202\250.drawio"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\227\240\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\347\237\251\351\230\265\345\255\230\345\202\250.png" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\346\227\240\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\347\237\251\351\230\265\345\255\230\345\202\250.png"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\227\240\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\347\237\251\351\230\265\345\255\230\345\202\250.png"
rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\346\227\240\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\347\237\251\351\230\265\345\255\230\345\202\250.png"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\227\240\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\350\241\250\345\255\230\345\202\250.drawio" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\346\227\240\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\350\241\250\345\255\230\345\202\250.drawio"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\227\240\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\350\241\250\345\255\230\345\202\250.drawio"
rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\346\227\240\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\350\241\250\345\255\230\345\202\250.drawio"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\227\240\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\350\241\250\345\255\230\345\202\250.png" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\346\227\240\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\350\241\250\345\255\230\345\202\250.png"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\227\240\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\350\241\250\345\255\230\345\202\250.png"
rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\346\227\240\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\350\241\250\345\255\230\345\202\250.png"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\234\211\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\347\237\251\351\230\265\345\255\230\345\202\250.drawio" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\346\234\211\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\347\237\251\351\230\265\345\255\230\345\202\250.drawio"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\234\211\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\347\237\251\351\230\265\345\255\230\345\202\250.drawio"
rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\346\234\211\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\347\237\251\351\230\265\345\255\230\345\202\250.drawio"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\234\211\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\347\237\251\351\230\265\345\255\230\345\202\250.png" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\346\234\211\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\347\237\251\351\230\265\345\255\230\345\202\250.png"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\234\211\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\347\237\251\351\230\265\345\255\230\345\202\250.png"
rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\346\234\211\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\347\237\251\351\230\265\345\255\230\345\202\250.png"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\234\211\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\347\237\251\351\230\265\345\255\230\345\202\250\347\232\204\345\211\257\346\234\254.drawio" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\346\234\211\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\347\237\251\351\230\265\345\255\230\345\202\250\347\232\204\345\211\257\346\234\254.drawio"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\234\211\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\347\237\251\351\230\265\345\255\230\345\202\250\347\232\204\345\211\257\346\234\254.drawio"
rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\346\234\211\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\347\237\251\351\230\265\345\255\230\345\202\250\347\232\204\345\211\257\346\234\254.drawio"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\234\211\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\350\241\250\345\255\230\345\202\250.drawio" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\346\234\211\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\350\241\250\345\255\230\345\202\250.drawio"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\234\211\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\350\241\250\345\255\230\345\202\250.drawio"
rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\346\234\211\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\350\241\250\345\255\230\345\202\250.drawio"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\234\211\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\350\241\250\345\255\230\345\202\250.png" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\346\234\211\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\350\241\250\345\255\230\345\202\250.png"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\234\211\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\350\241\250\345\255\230\345\202\250.png"
rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\346\234\211\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\350\241\250\345\255\230\345\202\250.png"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2421.drawio" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2421.drawio"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2421.drawio"
rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2421.drawio"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2421.png" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2421.png"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2421.png"
rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2421.png"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2422.drawio" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2422.drawio"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2422.drawio"
rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2422.drawio"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2422.png" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2422.png"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2422.png"
rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2422.png"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2423.drawio" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2423.drawio"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2423.drawio"
rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2423.drawio"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2423.png" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2423.png"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2423.png"
rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2423.png"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2424.drawio" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2424.drawio"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2424.drawio"
rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2424.drawio"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2424.png" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2424.png"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2424.png"
rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2424.png"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2425.drawio" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2425.drawio"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2425.drawio"
rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2425.drawio"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2425.png" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2425.png"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2425.png"
rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2425.png"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2426.drawio" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2426.drawio"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2426.drawio"
rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2426.drawio"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2426.png" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2426.png"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2426.png"
rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2426.png"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\242\345\233\276\347\244\272.drawio" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\242\345\233\276\347\244\272.drawio"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\242\345\233\276\347\244\272.drawio"
rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\242\345\233\276\347\244\272.drawio"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\242\345\233\276\347\244\272.png" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\242\345\233\276\347\244\272.png"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\242\345\233\276\347\244\272.png"
rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\242\345\233\276\347\244\272.png"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\210\240\351\231\244\345\240\206\351\241\266\345\205\203\347\264\2401.png" "b/docs/cs-basics/data-structure/pictures/\345\240\206/\345\210\240\351\231\244\345\240\206\351\241\266\345\205\203\347\264\2401.png"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\210\240\351\231\244\345\240\206\351\241\266\345\205\203\347\264\2401.png"
rename to "docs/cs-basics/data-structure/pictures/\345\240\206/\345\210\240\351\231\244\345\240\206\351\241\266\345\205\203\347\264\2401.png"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\210\240\351\231\244\345\240\206\351\241\266\345\205\203\347\264\2402.png" "b/docs/cs-basics/data-structure/pictures/\345\240\206/\345\210\240\351\231\244\345\240\206\351\241\266\345\205\203\347\264\2402.png"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\210\240\351\231\244\345\240\206\351\241\266\345\205\203\347\264\2402.png"
rename to "docs/cs-basics/data-structure/pictures/\345\240\206/\345\210\240\351\231\244\345\240\206\351\241\266\345\205\203\347\264\2402.png"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\210\240\351\231\244\345\240\206\351\241\266\345\205\203\347\264\2403.png" "b/docs/cs-basics/data-structure/pictures/\345\240\206/\345\210\240\351\231\244\345\240\206\351\241\266\345\205\203\347\264\2403.png"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\210\240\351\231\244\345\240\206\351\241\266\345\205\203\347\264\2403.png"
rename to "docs/cs-basics/data-structure/pictures/\345\240\206/\345\210\240\351\231\244\345\240\206\351\241\266\345\205\203\347\264\2403.png"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\210\240\351\231\244\345\240\206\351\241\266\345\205\203\347\264\2404.png" "b/docs/cs-basics/data-structure/pictures/\345\240\206/\345\210\240\351\231\244\345\240\206\351\241\266\345\205\203\347\264\2404.png"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\210\240\351\231\244\345\240\206\351\241\266\345\205\203\347\264\2404.png"
rename to "docs/cs-basics/data-structure/pictures/\345\240\206/\345\210\240\351\231\244\345\240\206\351\241\266\345\205\203\347\264\2404.png"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\210\240\351\231\244\345\240\206\351\241\266\345\205\203\347\264\2405.png" "b/docs/cs-basics/data-structure/pictures/\345\240\206/\345\210\240\351\231\244\345\240\206\351\241\266\345\205\203\347\264\2405.png"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\210\240\351\231\244\345\240\206\351\241\266\345\205\203\347\264\2405.png"
rename to "docs/cs-basics/data-structure/pictures/\345\240\206/\345\210\240\351\231\244\345\240\206\351\241\266\345\205\203\347\264\2405.png"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\210\240\351\231\244\345\240\206\351\241\266\345\205\203\347\264\2406.png" "b/docs/cs-basics/data-structure/pictures/\345\240\206/\345\210\240\351\231\244\345\240\206\351\241\266\345\205\203\347\264\2406.png"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\210\240\351\231\244\345\240\206\351\241\266\345\205\203\347\264\2406.png"
rename to "docs/cs-basics/data-structure/pictures/\345\240\206/\345\210\240\351\231\244\345\240\206\351\241\266\345\205\203\347\264\2406.png"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\240\206-\346\217\222\345\205\245\345\205\203\347\264\2401.png" "b/docs/cs-basics/data-structure/pictures/\345\240\206/\345\240\206-\346\217\222\345\205\245\345\205\203\347\264\2401.png"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\240\206-\346\217\222\345\205\245\345\205\203\347\264\2401.png"
rename to "docs/cs-basics/data-structure/pictures/\345\240\206/\345\240\206-\346\217\222\345\205\245\345\205\203\347\264\2401.png"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\240\206-\346\217\222\345\205\245\345\205\203\347\264\2402.png" "b/docs/cs-basics/data-structure/pictures/\345\240\206/\345\240\206-\346\217\222\345\205\245\345\205\203\347\264\2402.png"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\240\206-\346\217\222\345\205\245\345\205\203\347\264\2402.png"
rename to "docs/cs-basics/data-structure/pictures/\345\240\206/\345\240\206-\346\217\222\345\205\245\345\205\203\347\264\2402.png"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\240\206-\346\217\222\345\205\245\345\205\203\347\264\2403.png" "b/docs/cs-basics/data-structure/pictures/\345\240\206/\345\240\206-\346\217\222\345\205\245\345\205\203\347\264\2403.png"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\240\206-\346\217\222\345\205\245\345\205\203\347\264\2403.png"
rename to "docs/cs-basics/data-structure/pictures/\345\240\206/\345\240\206-\346\217\222\345\205\245\345\205\203\347\264\2403.png"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\240\2061.png" "b/docs/cs-basics/data-structure/pictures/\345\240\206/\345\240\2061.png"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\240\2061.png"
rename to "docs/cs-basics/data-structure/pictures/\345\240\206/\345\240\2061.png"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\240\2062.png" "b/docs/cs-basics/data-structure/pictures/\345\240\206/\345\240\2062.png"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\240\2062.png"
rename to "docs/cs-basics/data-structure/pictures/\345\240\206/\345\240\2062.png"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\240\206\346\216\222\345\272\2171.png" "b/docs/cs-basics/data-structure/pictures/\345\240\206/\345\240\206\346\216\222\345\272\2171.png"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\240\206\346\216\222\345\272\2171.png"
rename to "docs/cs-basics/data-structure/pictures/\345\240\206/\345\240\206\346\216\222\345\272\2171.png"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\240\206\346\216\222\345\272\2172.png" "b/docs/cs-basics/data-structure/pictures/\345\240\206/\345\240\206\346\216\222\345\272\2172.png"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\240\206\346\216\222\345\272\2172.png"
rename to "docs/cs-basics/data-structure/pictures/\345\240\206/\345\240\206\346\216\222\345\272\2172.png"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\240\206\346\216\222\345\272\2173.png" "b/docs/cs-basics/data-structure/pictures/\345\240\206/\345\240\206\346\216\222\345\272\2173.png"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\240\206\346\216\222\345\272\2173.png"
rename to "docs/cs-basics/data-structure/pictures/\345\240\206/\345\240\206\346\216\222\345\272\2173.png"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\240\206\346\216\222\345\272\2174.png" "b/docs/cs-basics/data-structure/pictures/\345\240\206/\345\240\206\346\216\222\345\272\2174.png"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\240\206\346\216\222\345\272\2174.png"
rename to "docs/cs-basics/data-structure/pictures/\345\240\206/\345\240\206\346\216\222\345\272\2174.png"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\240\206\346\216\222\345\272\2175.png" "b/docs/cs-basics/data-structure/pictures/\345\240\206/\345\240\206\346\216\222\345\272\2175.png"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\240\206\346\216\222\345\272\2175.png"
rename to "docs/cs-basics/data-structure/pictures/\345\240\206/\345\240\206\346\216\222\345\272\2175.png"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\240\206\346\216\222\345\272\2176.png" "b/docs/cs-basics/data-structure/pictures/\345\240\206/\345\240\206\346\216\222\345\272\2176.png"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\240\206\346\216\222\345\272\2176.png"
rename to "docs/cs-basics/data-structure/pictures/\345\240\206/\345\240\206\346\216\222\345\272\2176.png"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\240\206\347\232\204\345\255\230\345\202\250.png" "b/docs/cs-basics/data-structure/pictures/\345\240\206/\345\240\206\347\232\204\345\255\230\345\202\250.png"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\240\206\347\232\204\345\255\230\345\202\250.png"
rename to "docs/cs-basics/data-structure/pictures/\345\240\206/\345\240\206\347\232\204\345\255\230\345\202\250.png"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\273\272\345\240\2061.png" "b/docs/cs-basics/data-structure/pictures/\345\240\206/\345\273\272\345\240\2061.png"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\273\272\345\240\2061.png"
rename to "docs/cs-basics/data-structure/pictures/\345\240\206/\345\273\272\345\240\2061.png"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\273\272\345\240\2062.png" "b/docs/cs-basics/data-structure/pictures/\345\240\206/\345\273\272\345\240\2062.png"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\273\272\345\240\2062.png"
rename to "docs/cs-basics/data-structure/pictures/\345\240\206/\345\273\272\345\240\2062.png"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\273\272\345\240\2063.png" "b/docs/cs-basics/data-structure/pictures/\345\240\206/\345\273\272\345\240\2063.png"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\273\272\345\240\2063.png"
rename to "docs/cs-basics/data-structure/pictures/\345\240\206/\345\273\272\345\240\2063.png"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\273\272\345\240\2064.png" "b/docs/cs-basics/data-structure/pictures/\345\240\206/\345\273\272\345\240\2064.png"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\273\272\345\240\2064.png"
rename to "docs/cs-basics/data-structure/pictures/\345\240\206/\345\273\272\345\240\2064.png"
diff --git "a/docs/cs-basics/data-structure/pictures/\346\240\221/\344\270\255\345\272\217\351\201\215\345\216\206.drawio" "b/docs/cs-basics/data-structure/pictures/\346\240\221/\344\270\255\345\272\217\351\201\215\345\216\206.drawio"
new file mode 100644
index 00000000000..f8fe81d2c06
--- /dev/null
+++ "b/docs/cs-basics/data-structure/pictures/\346\240\221/\344\270\255\345\272\217\351\201\215\345\216\206.drawio"
@@ -0,0 +1 @@
+7Vtbk6I4FP41eZwukgBJHr1g727tVk1VV+30PNKSVmbQuIit7q/fBAISBLVbFHfa8sHkJORyzpcv5xwR4MFs8xj7i+lfIuARQFawAXgIEILQcuWXkmwzCWMkE0ziMNCddoKn8F+uhZaWrsKAL42OiRBREi5M4VjM53ycGDI/jsXa7PYqInPWhT/he4KnsR/tS7+FQTLNpBSRnfw3Hk6m+czQZVnLzM87650sp34g1iUR9gAexEIkWWm2GfBIKS/XS/bcqKG1WFjM58kpD6yenT8ev/39O3VCf/C2ZpuF7X/Ro7z50UpvGCA3kuP1X9SSk63Wg/vPSq2z/yrmyZdlaqWe7ICcxWbXKEsT9d3Lx5CLecmFWgnFiEiuThpRVvrraZjwp4U/Vi1riSMpmyazSNagLPrLRWbZ13DDA7WIMIoGIhJxOhB+feXueCzlyyQWP3mpJSDsxbKKyd94nPBNo/pgYRSJZi5mPIm3sot+gGBtRw1kzHR9XYKFFk1LiMhlvgbipBh5ZytZ0OZ6h+lQjemqKp4HPXUGZG0u5txUq9x3vH0uV76XK0O1b6uobXUtm4MHe6emoke5DrGKx/zABrA+zn484ckxjO7bpaR3p0bvuSzmkZ+Eb+Zy64yhZ/gqQrmRndktYpidWBV7ZtvUT5WPX3Ug5jwgaiMCkU1sN1+JHtYm1GzF5iyZkvZmSYFT6OTjWMKNNLBc+POPM0GJTDLBoJ4aClk23a/BGJSajGF3zRj2tazc/0RWdq0bs7JzLSsPP5GVHWRa2SEdW9m9lpUfP5GVmXtjVibn+nibMHkulb/nPp0s7xw8Vcn9u8IrLCpX9grt/4NX6FaAQuAHvUKKqIk4hq7q+NFzAVYbRFhH4JLD0irBEh6EZQcAc7oEGKneN+yjYYdDD4UdrNOwg52JvhZR4Z6ICtwlKiiCDy7GDrapdEgQNI3pUPjAIGO27AZtNw9c301J2D2AGIdada1XAkxOs5d3e7xP5Pa49MbcHliXljzX7zl8wdT7Pccusi78HqvelldyfMw8FWQmcCB8INAhiBIHOZhWhj/5zrJqh8nvLFq7hGsxEGpkIEU0LTKQfYSBsukaGEiSQWIeCZNB9JEp040W+VE4mcvqWCKYS3lfUUs49qOebpiFQRA1cVssVvNAMdmwLW5ilfSKtc9Ndg3e0cW4qTlX2jIA0B0AilOcyuXUOQCa06gtA8C9AyD1R28NAM0Z1pYBAO8ASC/8CgBo1wBw971R6QI+6arWoqkHESdTMRFzP/pTiIU2yA+eJFv9zoO/SkRDbsV6cDpKxuVvXHwwGXeys3meOeqypBcJCkefKCik1q0Fha3lKt+V2n5/Cr3N80dOPICdpqWgZQZsxIwKXYjrWt8bFbKDmUwJzy7zUnWZzIu4BM7dJZAthNyYS5APfHkAkDsAFBlUg4LOAdD8JmXLAMB3AKhLxb41ADQnBs/zQod9rzcalF/DOOhm/jIWJpXf2N3OLYz3/c1LhH35j+NZ1HdtlzPH8VGXM+vYVdCHarJwngP6Huh5wLOBjNV6EHguYBZgA+AhQNOCycnjInbanToZXzGG8f5BfAyT6epFjUk9wCjwGKAEMDkLVZOq6RxAKWCoiY31KoYFp8en0AK0a+8FORnrA+apQs8GdNjKJr8OR0dXL/crNSA9EbXfEWCuXotUvlIFAT1c0glRBUZSWwxAv5d2HqUFojrkx/rmOCzyX3jU98c/J6m8OrlUjT7D0Nb1UijeTz8theLQZEIb7zNhQXtnUqGs7v6SkoVHuz/2YO8/
\ No newline at end of file
diff --git "a/docs/cs-basics/data-structure/pictures/\346\240\221/\344\270\255\345\272\217\351\201\215\345\216\206.png" "b/docs/cs-basics/data-structure/pictures/\346\240\221/\344\270\255\345\272\217\351\201\215\345\216\206.png"
new file mode 100644
index 00000000000..3ad5782c8bd
Binary files /dev/null and "b/docs/cs-basics/data-structure/pictures/\346\240\221/\344\270\255\345\272\217\351\201\215\345\216\206.png" differ
diff --git "a/docs/cs-basics/data-structure/pictures/\346\240\221/\344\270\255\345\272\217\351\201\215\345\216\2062.drawio" "b/docs/cs-basics/data-structure/pictures/\346\240\221/\344\270\255\345\272\217\351\201\215\345\216\2062.drawio"
new file mode 100644
index 00000000000..31e3097a914
--- /dev/null
+++ "b/docs/cs-basics/data-structure/pictures/\346\240\221/\344\270\255\345\272\217\351\201\215\345\216\2062.drawio"
@@ -0,0 +1 @@
+5ZhNc5swEIZ/jY/uYLDBHGPsuIdmpmMfmhxlkEGtYKkQBvLrK1niq46bJm0Zpj6hfSWtpH12NSMmlheXW4bS6AECTCemEZQTaz0xzdnMsMVHKpVSXNdRQshIoAe1wp48Yy0aWs1JgLPeQA5AOUn7og9Jgn3e0xBjUPSHHYH2V01RiC+EvY/opfqFBDxS6tJ0Wv0jJmFUrzyzXdUTo3qwPkkWoQCKjmRtJpbHALhqxaWHqQxeHRc17/5Kb7MxhhP+OxN22UPg7CLH2z06MV1Pt0bxPNVeTojm+sAT06bC3+ogt8wrHQf7ey73uTpCwqfZmdKdGGAu0rLtFK1Qfu9qH2Izh1rUQWg8mmJ3AqIwVkVEON6nyJc9hcgjoUU8psKaiSbKUkX2SEocyE0QSj2gwM6OrOMR274v9Iwz+IY7PYHjHgyjWfyEGcfl1fDNGigimzHEmLNKDNET7DojdSLPa7vopIWWok5G1BrSiRg2nltWoqFxvQGdeRVdlqLk/fQ6CaAE72WcjaaW+z8oO+7IKFtDUV7dEOW5NTLK86Eor2+IsjUfGeXFUJS3N0R56bjjomwPRXlzQ5QX5shq2bmMaCAeDtpMIJGhZZAngQzaWoYBGI8ghATRTwCpDu9XzHmlnz0o59APvogOqx7l/A+L2nzq9q1L7VxZlbbey0ie4deExJEhZz5+/U3BEQsxf23cJXGGKeLk1N/HX+e3HKpK72+oSh1jZFXqDlOlJeGdIhXWU12Vot2WqDT+fYX+QUXpqZ+BCI/ty/enu7e5i2sX6kbQs7p/IN7qSF0ZF47O6JvzvJQNwmx/pKjh7e8oa/MD
\ No newline at end of file
diff --git "a/docs/cs-basics/data-structure/pictures/\346\240\221/\344\270\255\345\272\217\351\201\215\345\216\2062.png" "b/docs/cs-basics/data-structure/pictures/\346\240\221/\344\270\255\345\272\217\351\201\215\345\216\2062.png"
new file mode 100644
index 00000000000..fe6956b9d09
Binary files /dev/null and "b/docs/cs-basics/data-structure/pictures/\346\240\221/\344\270\255\345\272\217\351\201\215\345\216\2062.png" differ
diff --git "a/docs/cs-basics/data-structure/pictures/\346\240\221/\345\205\210\345\272\217\351\201\215\345\216\206.drawio" "b/docs/cs-basics/data-structure/pictures/\346\240\221/\345\205\210\345\272\217\351\201\215\345\216\206.drawio"
new file mode 100644
index 00000000000..b92e5c29cc9
--- /dev/null
+++ "b/docs/cs-basics/data-structure/pictures/\346\240\221/\345\205\210\345\272\217\351\201\215\345\216\206.drawio"
@@ -0,0 +1 @@
+7Vtbk6I4FP41eZwuIDfyKIq9D7tVU9u1tTOPKGllGo2L2Or8+k0kIEFQ2xvOtOWDyUnI5ZwvJ985IoDdyeo5CWbjv0TIY+BY4QrAHnAc27aI/FKSdSZhjGaCURKFutNW8BL95FpoaekiCvnc6JgKEafRzBQOxXTKh6khC5JELM1uryI2Z50FI74jeBkG8a703yhMx5nUdehW/gePRuN8ZpuwrGUS5J31TubjIBTLkgj6AHYTIdKsNFl1eayUl+sle67f0FosLOHT9JgHEuvvH2+rZPbTI6O56/T+WTrPX/Qo70G80BsGDonleN5ALTldaz2Q/xZqnd6rmKZf5hsrdWQHB89W20ZZGqnvTj6GXMwgF2olFCM6cnXSiLLiLcdRyl9mwVC1LCWOpGycTmJZs2UxmM8yy75GKx6qRURx3BWxSDYDwddXToZDKZ+niXjjpZaQsoFlFZO/8yTlq0b12YVRJJq5mPA0Wcsu+gGCtB01kCHW9WUJFlo0LiEilwUaiKNi5K2tZEGb6wOmc2pMV1XxNOyoMyBrUzHlplrlvpP1t3Lle7nSU/u2itpa17I5eLhzaip6lOsQi2TI92wA6uMcJCOeHsLorl1Kesc1es9lCY+DNHo3l1tnDD3DVxHJjWzNblPD7IRU7JltUz9VPn6VgaiFnxwXOdR2EEUkX4keFkHXbIXmLJmSdmbZAKfQyelYgo1uYD4Lpqd7gpIzyQTdetdQyLLpfg+PQZnpMVDbHgPdysreJ7Iytu/MyvhWVu59IisjaFoZw5atTG5l5edPZGWX3pmV6bkcbxWl30rl7zmnk+UtwVOVnN8VrLCo3JgVol+BFeIKUAg9lRVC10Qcdm5K/NxzAVYbRFgH4JLD0irB0t4LyxYAhtsEGKneN/hEgBHi7gs7cKthBzsTfRdEBTkSFbBNVFBoPxEIMUQulhe4bRoTI/uJ2YwhV7YgYtETXRIiexCDkVXXeiPA5Fz7+rTH/0S0B7M7oz12XVryXN6z/4Kp5z2HLrI2eI9Vb8sbER/XuDBsZl4n1H6iNqaSSGOJIrcy/NF3ll07TD4Jql3CrTyQ0+iBlKO5oAeyD3igbLoGDySdQWoeCdOD6CNTdjdaFMTRaCqrQ4lgLuWeci3RMIg7umEShWHc5NsSsZiGypP1LpV2typpd7Lrm1AN3p2r+abmXOmFAeA8AKCMS0wAoNYB0JxGvTAA8AMAGz56bwBozrBeGADwAQDl8qv0FLUNALLLRiUFfNFVrUVTDyJJx2IkpkH8pxAzbZAfPE3X+p2HYJGKhtyK9YRbSsblb1ycmIw7mmyeZ466LOlVgsL+JwoKqX1vQeHFcpUfSm1/PIV+yfNHjzyAraalmBmvUTMoxBTWtX40KHT3JjIlOttMS9UlMq/CCMiDEcgW4t4ZI8gHvj4A6AMAyhmgewNA84uUFwYAegAAlH4PuxsANOcFzyOhHa/nd/vltzD2sszfxsKk+hN76xaGu3TzGlFf/tt4FvTdmnHmOD7IOLOObcV8Tk0SzsfA80HHBz4CMlTr2MAngFmAdYHvAHdTMH3ysAidtqdOhleMQbh7EJ+jdLwYqDFdHzAX+Ay4FDA5i6smVdNh4LqAOU3eWK+iV/j05Bi3YKPae0FOxjzAfFXoIOD2LrLJr73+wdXL/UoNSCai9tsHjOi1SOUrVVDQgSWdUFVgdGOLLvA6m879TYGqDjmVuzsfFgcDHnvB8G20kVcnl6rRZ9hGul6KxL3N50KReOVdkCIfVvKEhds70xXK6vYfKVl4tP1fD/T/Bw==
\ No newline at end of file
diff --git "a/docs/cs-basics/data-structure/pictures/\346\240\221/\345\205\210\345\272\217\351\201\215\345\216\206.png" "b/docs/cs-basics/data-structure/pictures/\346\240\221/\345\205\210\345\272\217\351\201\215\345\216\206.png"
new file mode 100644
index 00000000000..5c80cedf7d6
Binary files /dev/null and "b/docs/cs-basics/data-structure/pictures/\346\240\221/\345\205\210\345\272\217\351\201\215\345\216\206.png" differ
diff --git "a/docs/cs-basics/data-structure/pictures/\346\240\221/\345\220\216\345\272\217\351\201\215\345\216\206.drawio" "b/docs/cs-basics/data-structure/pictures/\346\240\221/\345\220\216\345\272\217\351\201\215\345\216\206.drawio"
new file mode 100644
index 00000000000..c324e801447
--- /dev/null
+++ "b/docs/cs-basics/data-structure/pictures/\346\240\221/\345\220\216\345\272\217\351\201\215\345\216\206.drawio"
@@ -0,0 +1 @@
+7VvLluI2EP0aLacPlqzXEoPpLJKcySHJPHZurAZnDCLGdEN/fSQsGwtsoHmZTHNYIJVkPaqurqoKA1BnvHhMgunoNxmKGMBWuACoCyB0nBZRX1qyzCSc00wwTKLQdFoL+tGbMMKWkc6jUMysjqmUcRpNbeFATiZikFqyIEnkq93tWcb2rNNgKLYE/UEQb0u/RGE6yqQM0rX8FxENR/nMDuFZyzjIO5udzEZBKF9LIuQD1EmkTLPSeNERsVZerpfsuV5Na7GwREzSQx6I2vhvtYG/fv/jz7cvuP+9P38bfTKjvATx3GwYQBKr8bwnveR0afRA/p3rdXrPcpJ+mq2s1FYdIJ4u1o2qNNTf7XwMtZinXGiUUIwI1eqUEVXFex1FqehPg4FueVU4UrJROo5VzVHFYDbNLPscLUSoFxHFcUfGMlkNhJ6fBRkMlHyWJvKHKLWElD+1WsXkLyJJxaJWfU5hFIVmIcciTZaqi3mA5HY0QIbU1F9LsDCiUQkRuSwwQBwWI69tpQrGXO8wHaww3aaKJ2FbnwFVm8iJsNWq9p0sv5Yr38qVrt53q6gtTS2bQ4Rbp2ZDj2odcp4MxI4NIHOcg2Qo0n0Y3bZLSe+4Qu+5LBFxkEYv9nKrjGFm+CwjtZHC7DjnK2N2vGnPbJvmqfLx2xiIMPwAmQupA13qknwlZliEmd2K7FkyJW3NsgJOoZPjsYRqaWA2DSbHM0GJTDJBp5oaClk23c/BGJTajIGaZgz3Wlb2PpCVXX5jVsbXsnL3I1nZsa3s4oatTK5l5ccPZGWGb8zK9FQfbxGlX0vlb7lPp8prB09Xcv+u8AqLypW9Qvd/4RVuAAXzI71C6jAbcRRe1fFjpwKsMoho7YFLDstWCZbOTlg2ADDcJMDI5n1Djw07XLYr7KCNhh38RPSdERXkQFSgJlFBHeeBIISRy7C6wB3bmC5xHrjDuctUi0ta9EhKgmQHYtS4TSImPxaX93v8D+T3YHpjfo9TlZc81fHZfcNUOz77brImHJ9WtS2v5PkQ68ZwuH2fcOeBOphCRjHEiG0MfygF4eph8kmql3AtBoK1DKSJ5owMRPcwUDZdDQMpMkjtI2EziDkyZboxoiCOhhNVHSgECyX3NLVEgyBum4ZxFIZxHbclcj4JNZN1z8VNzOamgnRKeHcr8A4vxk31ydIzAwDdAaCN69oAQI0DoD6PemYAkDsAVg7prQGgPsV6ZgA4dwCAUkp9HYM0DACy7Y0qF7BvqkaLth5kko7kUE6C+Fcpp8Yg/4g0XZqXHoJ5KmuSK60H3FA2Ln/l4shs3MHO5mnmqEqTXiQo7H2goJDwWwsKz5asfFdu+/059HOeP3rgAWw0L8XseI3aQaHLkdXKjkxMsZ2pTAXPRhNTVbnMi/gE7t0n0OxEbswnyAe+PADwHQCaDeCtAaD+XcozAwDeAaDvLnRrAKjPDJ7mhnZ9r/fYKb9Vu9PP/GksTDZ/ZW/cwmjb4bxE3Jf/PJ6Ffdf2OXMc7/U5s45NRX2wIg3nY+D5oO0D3wUqWGs7wCdAxTG8A3wI2Kpgc/KgCJ7Wp04FWJwjtH0QH6N0NH/SYzIfcAZ8DpQzy9UsTE+qp8OAMcBhHRubVXQLTk8OoQXHrbwX1GTcA9zXhbYLWPcsm/zc7e1dvdqv0oBHV/vtAU7MWpTytSooaKOSTqgucLqyRQd47VXn3qpAdYc8Yrw5DouDJxF7weDHcCXfnFypxpxhxzX1UizurT6XicUR3GbCgvZOpEJVXf8pJQuP1n/tQf5/
\ No newline at end of file
diff --git "a/docs/cs-basics/data-structure/pictures/\346\240\221/\345\220\216\345\272\217\351\201\215\345\216\206.png" "b/docs/cs-basics/data-structure/pictures/\346\240\221/\345\220\216\345\272\217\351\201\215\345\216\206.png"
new file mode 100644
index 00000000000..87bf512ec50
Binary files /dev/null and "b/docs/cs-basics/data-structure/pictures/\346\240\221/\345\220\216\345\272\217\351\201\215\345\216\206.png" differ
diff --git "a/docs/cs-basics/data-structure/pictures/\346\240\221/\345\256\214\345\205\250\344\272\214\345\217\211\346\240\221.drawio" "b/docs/cs-basics/data-structure/pictures/\346\240\221/\345\256\214\345\205\250\344\272\214\345\217\211\346\240\221.drawio"
new file mode 100644
index 00000000000..69326285015
--- /dev/null
+++ "b/docs/cs-basics/data-structure/pictures/\346\240\221/\345\256\214\345\205\250\344\272\214\345\217\211\346\240\221.drawio"
@@ -0,0 +1 @@
+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
\ No newline at end of file
diff --git "a/docs/cs-basics/data-structure/pictures/\346\240\221/\345\256\214\345\205\250\344\272\214\345\217\211\346\240\221.png" "b/docs/cs-basics/data-structure/pictures/\346\240\221/\345\256\214\345\205\250\344\272\214\345\217\211\346\240\221.png"
new file mode 100644
index 00000000000..564685ab7b7
Binary files /dev/null and "b/docs/cs-basics/data-structure/pictures/\346\240\221/\345\256\214\345\205\250\344\272\214\345\217\211\346\240\221.png" differ
diff --git "a/docs/cs-basics/data-structure/pictures/\346\240\221/\345\271\263\350\241\241\344\272\214\345\217\211\346\240\221.drawio" "b/docs/cs-basics/data-structure/pictures/\346\240\221/\345\271\263\350\241\241\344\272\214\345\217\211\346\240\221.drawio"
new file mode 100644
index 00000000000..11133b532ad
--- /dev/null
+++ "b/docs/cs-basics/data-structure/pictures/\346\240\221/\345\271\263\350\241\241\344\272\214\345\217\211\346\240\221.drawio"
@@ -0,0 +1 @@
+7VnJdpswFP0aL+OjiWmZOEm7SIdzsmjSHQbZcAqIynKM+/UVRmIysR2SYKfuCr0r8TTcq6eHGOFJnH3ibhp8YT6NRgj42QhfjxCCEJjykSPrAnEcqwDmPPRVowq4D/9QBQKFLkOfLhoNBWORCNMm6LEkoZ5oYC7nbNVsNmNRs9fUndMt4N5zo230R+iLoEBtZFX4ZxrOA90zNJ2iJnZ1YzWTReD6bFWD8M0ITzhjoijF2YRG+eLpdSneu32mthwYp4k45IU7eumBOPrJb52v09m3AKzusgvl5cmNlmrCI2RG0t/VVBbmeUE+3TiVhWS6SAt702DGZL9yWmKt1sr8vWS64mKxYfJSNkBGmlWV2ivQbuSAC09lbxqujQA1OkJyYpJ/aVytglDQ+9T18pqVlKDEAhFH0oKy6C7SQhSzMKN+PrYwiiYsYnzjCM9m1PQ8iS8EZ79orca3nCkAZedPlAuaPbvysORTbgTKYir4WjZRL2BTSUDtAaTtVU1RCgpqYtKYqzQ8Lz1XNMuCYvoFrKMO1ttLnPiX+faRVsIS2lxWOW++fqgbj3XjOp83KK21svquPfW3tmhr5eXI2ZJ7dMeUsYodLp9TsW9DbDNZY8roYEpjnEauCJ+aw+2iT/XwnYWbTaSFQppCMYyWAoppqrfqe73tyGk5Ai1HxTpsOdqoqZx2f4Hhg8LKG4QRdEZhhLTUUarlWGGEPMvyInWT/qRuaQV201liRXf/BsslXafCsjHUXsZntJcRaLJM0JFZNodi2Tgjlg10Yixbr038slA81MqPOtGT5Srryw2d9JWpYmmcfKpIPmSqaPZMFQ1gNzVK0KCpov1aSXZ+i4A9AtNCBjUhw51C/hCSNI4pSdI+00hPSRJsj5FNkAURsYiJIG5lRN3VAwnWeRfBnnRENA+UHz6q/Bw8NjE2pDzkuYvKm0etRuCMHeg4xEYQEhNYPbXZErmBh/2y1vei7//RRc7oo6t9Q3f0RA12Xcy+NlPbfcB1Z2r7DtIPcSxC0M3+QKma0TivoNM8zUw4tqBhIdsyZDSxW+4PvvGzO93oTnDnEIaKWWiomGWeUcxqXxSVd7xHi1ldt77/Y1b3ddr+mIVON2YRuDOcvE3MImRnYOwds6RZ/XQtmle/rvHNXw==
\ No newline at end of file
diff --git "a/docs/cs-basics/data-structure/pictures/\346\240\221/\345\271\263\350\241\241\344\272\214\345\217\211\346\240\221.png" "b/docs/cs-basics/data-structure/pictures/\346\240\221/\345\271\263\350\241\241\344\272\214\345\217\211\346\240\221.png"
new file mode 100644
index 00000000000..673f3e32beb
Binary files /dev/null and "b/docs/cs-basics/data-structure/pictures/\346\240\221/\345\271\263\350\241\241\344\272\214\345\217\211\346\240\221.png" differ
diff --git "a/docs/cs-basics/data-structure/pictures/\346\240\221/\346\226\234\346\240\221.drawio" "b/docs/cs-basics/data-structure/pictures/\346\240\221/\346\226\234\346\240\221.drawio"
new file mode 100644
index 00000000000..6eeaa610144
--- /dev/null
+++ "b/docs/cs-basics/data-structure/pictures/\346\240\221/\346\226\234\346\240\221.drawio"
@@ -0,0 +1 @@
+5VhNc9owEP01HMnY+rCtY0LSdibNTKc5NOnN2AJ7KixXiGD667vGsi0bSGlKcTI5sfskrbT73grBCE8WxUcV5smdjLkYIScuRvh6hJDrOh58lMimQhjzK2Cu0thMaoH79Bc3oGPQVRrzZWeillLoNO+CkcwyHukOFiol191pMym6u+bhnO8A91EodtFvaayTCg2Q3+KfeDpP6p1dj1Uji7CebDJZJmEs1xaEb0Z4oqTUlbUoJlyUxavrUq37cGC0OZjimT5mwfT2s7i+U1/V7ePDOLv8TokYj02Up1CsTMIj5AmIdzUFY14a8BkucjCy6TKv/O2EmYR9IS29MbXyfq5kPTBebpm8hAmI5kU7WEd16jBw4CpSs1sNWydAnY0QJAb8g3O1TlLN7/MwKkfWIEHAEr0Q4Llghsu8EsUsLXhcni0VYiKFVNtAeDbjXhQBvtRK/uDWSOyzqeM0mz9xpXlxsPJuwyc0ApcLrtUGppgFxDcSMD2AqPHXlqIMlFhiqrHQaHjeRG5pBsMw/Resoz2s90ucxZdl+4CXyYx3ywp5q82D7TzaznWZt9N4G+O9tPY83mnRXuXh5HKlIv5MytjcHaGac/2nhthl0mKK7mGqxhQXoU6fusfdR5/Z4YtMt01UC4V2hUJxTwFVmmaV3eu9QNTpBiJ9KVV12Am0VVOT9ssFho+6Vk5wjbjv6BqhPXVgPPA1Qg6y/G+k7mgF7afzAPNvm2UP91rXHZhleq5exu+ol323xzIbmGXvXCyT98Qy632f+wOz7A/y8ONFqh8s+9Gy2yWl8yqeiuTIpyJ+VU9FcqqnIjvvUzE4lSQdW5LOkZJ0LUm6b1+SdEhJUoYvPIwpJgGF2991u69Vn10wlzESwAjxHP+FciXBBQoIfIHCz2riod4mqDeKz6plNsj1OqgyvbegTM95VpnBaZRJn1Um/k/KBLf9D7Ga3v4Ti29+Aw==
\ No newline at end of file
diff --git "a/docs/cs-basics/data-structure/pictures/\346\240\221/\346\226\234\346\240\221.png" "b/docs/cs-basics/data-structure/pictures/\346\240\221/\346\226\234\346\240\221.png"
new file mode 100644
index 00000000000..af12915808e
Binary files /dev/null and "b/docs/cs-basics/data-structure/pictures/\346\240\221/\346\226\234\346\240\221.png" differ
diff --git "a/docs/cs-basics/data-structure/pictures/\346\240\221/\346\273\241\344\272\214\345\217\211\346\240\221.drawio" "b/docs/cs-basics/data-structure/pictures/\346\240\221/\346\273\241\344\272\214\345\217\211\346\240\221.drawio"
new file mode 100644
index 00000000000..8379028d2a9
--- /dev/null
+++ "b/docs/cs-basics/data-structure/pictures/\346\240\221/\346\273\241\344\272\214\345\217\211\346\240\221.drawio"
@@ -0,0 +1 @@
+5VnLcpswFP0aL+PRG1gmTpq2M5nJTBZNuiNGNkwxogLHOF9fYSSMME5c2/WjXqF7JK4e5+jqCnp4MCnupZ+GDyLgcQ+BoOjh2x5CEAKmHiUyrxDPcypgLKNAN1oCT9E71yDQ6DQKeGY1zIWI8yi1waFIEj7MLcyXUszsZiMR272m/pivAE9DP15Ff0RBHlaoi5wl/pVH49D0DJlX1Ux801jPJAv9QMwaEL7r4YEUIq9Kk2LA43LxzLpU731ZU1sPTPIk3+SFZ4cW19/kzzALJmPy8P39HlxdaS9vfjzVE+4hFit/N6+qMC4L6ulPUlVIXrO0shcNRkL1q6aVz/Vasd9TYSqusgWT16oBommxrDRegXGjBlx5qnszcGMEyOoIqYkp/pVxMwujnD+l/rCsmSkJKizMJ7GyoCr6WVqJYhQVPCjHFsXxQMRCLhzh0Yiz4VDhWS7FL96oCRzvFYC68zcuc16sXXlY86k2AhcTnsu5aqJfwExLQO8BZOxZQ1EaChtiMpivNTyuPS9pVgXN9F+wjjpYby9xElyX20dZiUi4vaxq3nL+3DRemsZtOW9QW3Ntbbv2PFjZoq2VVyMXUznkH0wZ69jhyzHPP9sQq0w2mKIdTBlM8tjPozd7uF306R4eRbTYREYoxBYKpS0FVNPUbzX3etuR13IEWo6qdVhxtFBTPe3tBYY3Cit7CCPogsIIcZlFKqZHDiNkLctZ6ifbk7qiFdhNZ41V3f0fLCMMTotleqi9jC9oL0Nqs0zwkVlmh2KZXhDLBJLTYtnZNfErovy5UX4xiZ4qL7O+0jBJX50q1sbJp4rkLFNFtmWqSIFra5Sgg6aK7q6S7LyLgE8EZoQMGkKGHwr5LCRJjyrJ9pm29e3FdfvIJciBiDiEIYhbGVF39YEE6+1LsOcTEdmG8sPHlB/FXp9hTDFxqUo+ILTFCL2+Bz2PuKqGMOBsJ01C7DsYJYe9WJvPov/+zkUu6M6F4Yll47Dru+yuidrH51t3WPrsHD2LUxGCbvYPdCwC67iCnn2YObDvQOog16EqhLkt9xsfmbjTjemEdA7hUDFr/XeiPd8t2QXdLSk7tZjV9Qlh90x+/4lRnfv3oUObF9k+qO01MVIZj1xGasG41Nge4xncNKAdNc8intv3GEMeBESlWi61ZchAnzqk/ENKkUsZZdsFNIrtRIvsLdFS5vKna9V8+esa3/0B
\ No newline at end of file
diff --git "a/docs/cs-basics/data-structure/pictures/\346\240\221/\346\273\241\344\272\214\345\217\211\346\240\221.png" "b/docs/cs-basics/data-structure/pictures/\346\240\221/\346\273\241\344\272\214\345\217\211\346\240\221.png"
new file mode 100644
index 00000000000..c0f30c04c56
Binary files /dev/null and "b/docs/cs-basics/data-structure/pictures/\346\240\221/\346\273\241\344\272\214\345\217\211\346\240\221.png" differ
diff --git "a/docs/cs-basics/data-structure/pictures/\346\240\221/\351\223\276\345\274\217\345\255\230\345\202\250\344\272\214\345\217\211\346\240\221.drawio" "b/docs/cs-basics/data-structure/pictures/\346\240\221/\351\223\276\345\274\217\345\255\230\345\202\250\344\272\214\345\217\211\346\240\221.drawio"
new file mode 100644
index 00000000000..37585459182
--- /dev/null
+++ "b/docs/cs-basics/data-structure/pictures/\346\240\221/\351\223\276\345\274\217\345\255\230\345\202\250\344\272\214\345\217\211\346\240\221.drawio"
@@ -0,0 +1 @@
+7Zxbb9owFMc/DY+bcg95LPQyaUya2kntHl1iiFcTZ8bc+ul3HBxIloXCgMQPFkjEx5fE/h38z3EMPXc4Wz9wlCXfWIxpz7Hidc+97TmObVsBfEjLZmuJonBrmHISq0J7wxN5x8poKeuCxHheKSgYo4JkVeOYpSkei4oNcc5W1WITRqtnzdAU1wxPY0Tr1mcSi2Rr7Tvh3v4Fk2lSnNkOom3ODBWFVU/mCYrZqmRy73rukDMmtkez9RBTOXjFuGzr3Tfk7i6M41QcU2HgfX9xfi98h44e3r/es+dF9PbJUdcmNkWHcQz9V8mUpfAx4GyRxlg2Y0GKcZGwKUsRHTGWgdEG4y8sxEbRQwvBwJSIGVW5cIV88yLrf/aL5E/VXJ64XVdSG5WaC87e8JBRxvOLcy0rCPw+5ExYKkp2fyhfYN92R/ahcZSUac4WfIwPDU1fuRviUywOFfR2NOFrgNkMQx+gIscUCbKsXglS/jjdldsjgwNF7QSCriF4NkE76JKgZwge/modQbDfJUDfADwboOt0STAwBA/PjcdMop0SDA3BswmWbks7IKjEeonoQp3pFglUwwq30Zk8FOhVmsp0VgkR+ClD+WisIB7JRx5xoXh6EgUECgKRFHNVacwoRdmc5K3lsMYJofEIbdhCFOcpUjmuwqlkbUTJNIXjMVCRTQ6WmAsC4cONypiROM6vc0IoLYF27KF145/hGvJEeH3YOeooVQWvCK9UVOb1VXq1j3HsInBJSvFNaF2JftQIGnolCKKPEN2hdHoM8zrSmLPsR+H+0pAxIoHdLWHA5spWJqQmDJHPCzKT4klR95UJwWYqwdXY7BrNB8YfwBuGaijnCR96M4S0vU/DWxbnwDcFBwB/lG1gNBcrPBfX84pT7p0K1zjSM9xreUbhqqWJYSRhXNJf8rUDtPeXs12BAYgJzcP9BGYAnLbMNPo30xLEoFWGdo3hY35aA/F0iOsqwM6YOkawWxPsMNRNsO36wpNR7JYmhqZQSxvJ9oxknw7V1UyzfaPZl6Ooi2gHRrRbE+3+X6Ltel7Xol1fJjOi3dbM0PCQSRvRri/AGdH+EGqomWhHRrQvR1ET0XbqK2BGtK8l2pF2kfbuQY8R7dZFu+mRmC6i7dQX4Yxofwi1YQbobH53jWhfjqIuol1fAzOifS3R9m3dIm2nvinMiHZbM0PDhlxtRLu+CGdE+0OovmaiHRrRvhxFXUTbbEJrT7SDqCrau1/KdCfaZhdad6Kt+Ta0omEj2qdA1Wwfmmv2oV2Qoiai7dbXwIxoX020tds57pqNaJ2JdtOvtrQRbbMR7T+garYRzTUb0S5I8eqiDcn9nxrkeaW/hnDv/gA=
\ No newline at end of file
diff --git "a/docs/cs-basics/data-structure/pictures/\346\240\221/\351\223\276\345\274\217\345\255\230\345\202\250\344\272\214\345\217\211\346\240\221.png" "b/docs/cs-basics/data-structure/pictures/\346\240\221/\351\223\276\345\274\217\345\255\230\345\202\250\344\272\214\345\217\211\346\240\221.png"
new file mode 100644
index 00000000000..c0ce15b72e4
Binary files /dev/null and "b/docs/cs-basics/data-structure/pictures/\346\240\221/\351\223\276\345\274\217\345\255\230\345\202\250\344\272\214\345\217\211\346\240\221.png" differ
diff --git "a/docs/cs-basics/data-structure/pictures/\346\240\221/\351\241\272\345\272\217\345\255\230\345\202\250.drawio" "b/docs/cs-basics/data-structure/pictures/\346\240\221/\351\241\272\345\272\217\345\255\230\345\202\250.drawio"
new file mode 100644
index 00000000000..1ddbb02dc6e
--- /dev/null
+++ "b/docs/cs-basics/data-structure/pictures/\346\240\221/\351\241\272\345\272\217\345\255\230\345\202\250.drawio"
@@ -0,0 +1 @@
+7V1dc5s4FP01PDYDSAh49FfSh3amu+nMto8yyDYtRi6WE3t//UogMGCwiSHgjZlkJuiCJXHP0dXVMSgKmKz3TyHerL5Sl/iKrrp7BUwVXdc0FfE/wnKILbZtxoZl6LnyoqPh2fuXSKMqrTvPJdvchYxSn3mbvNGhQUAclrPhMKSv+csW1M+3usFLcmJ4drB/av3Hc9kqtlq6ebR/Jt5ylbSsITs+s8bJxfJOtivs0teMCcwUMAkpZfHRej8hvnBe4pf4c48VZ9OOhSRgdT7w9OMPePm6oQxPv88OwRr9+uvwSY9recH+Tt6woiOf1zeeiy6zg/QD+rMT/RwvaMA+bSOURvwC3djsjyf50VL8HSV18M7ME6N0QlqjznvHQeSF8evKY+R5gx1x5pXziNtWbO3zksYP8XYTI7vw9sQVnfB8f0J9GkYVgcWCIMfh9i0L6W+SOeOa9lxV08ZfSMjIvtJ9WgoKZzOha8LCA79EfsBMcJREBglDXzO0kKZVhhGJDUsiLtOaj1jxAwnXG6ADJdAVXRy4IzEGeCmgAcm7ld93ePiRLfzMFqbivtW0dJCluA3inoyagh95P+gudMiZG4ByOONwSdgljp7ikvG7UeL3xBYSHzPvJd/dMjBkC9+ox28khR0l8UrCjvQCnvFtyk9lh1+hItMyHnQL6qamQxOipCcJm2wrfxbkW4mddNJKRJzUJ9dzCVaGge0GB9dHgkwwiQ2T8tCQ2uLmPkbEsMx8xIB9RwyjK5THd4SyYd8YyqgrlKf3hLJWQNnuGWWzK5Sf7ghl27gxlK2mOd7eYz8yxz+TnI4fHxM8UUjyuzQrTAsdZ4XG/yIrLBAFgSuzQkuzchUZmt5p4mc3JVjpIkK9QJeElmqGltpZWvZAMNQnwczCfJPOP29edkDrzLIDar0uO5Kbupp+LdLCrEkL2CctLE17QAAYAFoGn8G1PJqGqj3Ymm1Di5+BSDWvjEk6OkMZQ1V7pYzWVeIzu6PEBxWXqn0nPsk02Grmc36KKc98Lk1lPUxMWgWWHaU+KDdlaHaeOEB7MDXD1C3T0A1gFaqvG4KQXVpN0oha2oWuIlCZ8PouEejzHUUgCAoJj9l3BCrTRK+JQPWT3OuS6RYjEKobgcANRyDrbHBoJwIZ2tkw994RqFrIFYGmxQikXYhAcXMVEYgHA5YfEvkIIodMNtxIE/a9ZcCLDmcw4faxCC2eg/2RPLH2XNevim0h3QWuiGTTtrIjKx+bgH4am2AJ34tfFbUXm6o13pYJoA8EEMMdFtLj3glQLf+2TAAwEEBkGfqtEaBMGX4XAsCBAALcwgLZUPsmQJly+y4EMAYCKBmF/1YIkFT8/gSwBgIop98AGyUSWbcEKFNCC97frvBGHDI89wvL0zKnbfnChclnMIXbHI4s9gLh/egzDvV9vNl6UWXxFSvPd7/gA92xpJmkVNQRXEysRamOgByLzBdtBWqUgwkh4wQmpHYpJCSw1MGJ3yfzsP83cRgOlnUgO4XEDenme7KCF4aNWIeScPbCXbiVtpLxxuhGnvTJIvnsnDJG17IQSm+llUauMsb8lztvoj4YisHvZsLL2rHMf8XlIZvQgEOPvQhIgrfslWxZXdTPDIGzOkQp1vDdsK7WBmsHZbVWUPZ4dNs3CcxNKBc9ao2PlGvMJsrRX/iRkLbiUZ0EzWih16BFl6yofryyZVaoAyPexIh9ng29EaQFQa8eQRoJevdLEK1kvd8tQ1pQ/OoxpJHid8cMsfpmSAuSYD2GNJIE75chKfS9MaQFzbAeQxpphvfLEFCiKXXLkBZExXoMaSQq3jFD+s5UQQuqYz2GoIEh1zCk7JupbhlS/YBmywwxB4ZcxZC+M1VQJoi+C0MafXNxvwwx+s5UQY132wfJvFXJ/JCHtDcFHXSmlcYtDAGiegDejoIOygTSAY4bka9BZ+Jkxc4yw3g9T5De5WvQmTg5HhhyFUN6XxR0Jk5e2oJmYMhtytegM3FyOjDkGob0Ll/DzsTJS+8GDwy5TfkadiZOPg4MuYYhvcvXsDNx8tLGSgNDblO+htXPeJ7A2IwynyvZUGN71ftlSO/yNYQnaIjXs59lUXow/4YCDdmKLmmA/S80cq1A5xdh7CCfx8c7RvPYHTeseDCUfjbrksHy2s26ar8I3gyOzva9vDTpf6QNG8zivpd9bxkDy1TIoo9r7WWmvmU0vX2LvRbHH6y7Z0yvu1bZ+b0UzPyGDQYAZWffumGDfX6jM7vXXatgZ+9rN3ps5sO8rGeifHDq/W1N2Nn72o2eivkwBLD1GyOAUaJNzQxlPFNGM2UGFZ47jDRlhhQ+jdoTZaYrVnSQJ4mTzuVHHvD53rZFSlykxpPHVru5qNOaKbalzGzFMhWbt2KJRkVzhmJZiq1X0UP2ItVD52EdomqwlKi8MXus2DNxMIKKNW3lJr9NHy/2nt8v9wAfGeJ+HxUbyb5w5wtXmMoIZHxiigPbjLCYKONRdPFjdGCKC5IE5uaGjY/nxB9j5/cyshcb566RSwkNynImNRxHP+0MPlTYLgWVDL50pDUcfbx4/Bcq8XR9/Ec0YPYf
\ No newline at end of file
diff --git "a/docs/cs-basics/data-structure/pictures/\346\240\221/\351\241\272\345\272\217\345\255\230\345\202\250.png" "b/docs/cs-basics/data-structure/pictures/\346\240\221/\351\241\272\345\272\217\345\255\230\345\202\250.png"
new file mode 100644
index 00000000000..33f3c6e3ff3
Binary files /dev/null and "b/docs/cs-basics/data-structure/pictures/\346\240\221/\351\241\272\345\272\217\345\255\230\345\202\250.png" differ
diff --git "a/docs/cs-basics/data-structure/pictures/\346\240\221/\351\241\272\345\272\217\345\255\230\345\202\2502.drawio" "b/docs/cs-basics/data-structure/pictures/\346\240\221/\351\241\272\345\272\217\345\255\230\345\202\2502.drawio"
new file mode 100644
index 00000000000..8048a1a724c
--- /dev/null
+++ "b/docs/cs-basics/data-structure/pictures/\346\240\221/\351\241\272\345\272\217\345\255\230\345\202\2502.drawio"
@@ -0,0 +1 @@
+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
\ No newline at end of file
diff --git "a/docs/cs-basics/data-structure/pictures/\346\240\221/\351\241\272\345\272\217\345\255\230\345\202\2502.png" "b/docs/cs-basics/data-structure/pictures/\346\240\221/\351\241\272\345\272\217\345\255\230\345\202\2502.png"
new file mode 100644
index 00000000000..70c6da26d22
Binary files /dev/null and "b/docs/cs-basics/data-structure/pictures/\346\240\221/\351\241\272\345\272\217\345\255\230\345\202\2502.png" differ
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204/\345\215\225\351\223\276\350\241\2502.png" "b/docs/cs-basics/data-structure/pictures/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204/\345\215\225\351\223\276\350\241\2502.png"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204/\345\215\225\351\223\276\350\241\2502.png"
rename to "docs/cs-basics/data-structure/pictures/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204/\345\215\225\351\223\276\350\241\2502.png"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204/\345\217\214\345\220\221\345\276\252\347\216\257\351\223\276\350\241\250.png" "b/docs/cs-basics/data-structure/pictures/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204/\345\217\214\345\220\221\345\276\252\347\216\257\351\223\276\350\241\250.png"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204/\345\217\214\345\220\221\345\276\252\347\216\257\351\223\276\350\241\250.png"
rename to "docs/cs-basics/data-structure/pictures/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204/\345\217\214\345\220\221\345\276\252\347\216\257\351\223\276\350\241\250.png"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204/\345\217\214\345\220\221\351\223\276\350\241\250.png" "b/docs/cs-basics/data-structure/pictures/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204/\345\217\214\345\220\221\351\223\276\350\241\250.png"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204/\345\217\214\345\220\221\351\223\276\350\241\250.png"
rename to "docs/cs-basics/data-structure/pictures/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204/\345\217\214\345\220\221\351\223\276\350\241\250.png"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204/\345\276\252\347\216\257\351\230\237\345\210\227-\345\240\206\346\273\241.png" "b/docs/cs-basics/data-structure/pictures/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204/\345\276\252\347\216\257\351\230\237\345\210\227-\345\240\206\346\273\241.png"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204/\345\276\252\347\216\257\351\230\237\345\210\227-\345\240\206\346\273\241.png"
rename to "docs/cs-basics/data-structure/pictures/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204/\345\276\252\347\216\257\351\230\237\345\210\227-\345\240\206\346\273\241.png"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204/\346\225\260\347\273\204.png" "b/docs/cs-basics/data-structure/pictures/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204/\346\225\260\347\273\204.png"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204/\346\225\260\347\273\204.png"
rename to "docs/cs-basics/data-structure/pictures/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204/\346\225\260\347\273\204.png"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204/\346\240\210.png" "b/docs/cs-basics/data-structure/pictures/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204/\346\240\210.png"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204/\346\240\210.png"
rename to "docs/cs-basics/data-structure/pictures/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204/\346\240\210.png"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204/\346\240\210\345\256\236\347\216\260\346\265\217\350\247\210\345\231\250\345\200\222\351\200\200\345\222\214\345\211\215\350\277\233.drawio" "b/docs/cs-basics/data-structure/pictures/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204/\346\240\210\345\256\236\347\216\260\346\265\217\350\247\210\345\231\250\345\200\222\351\200\200\345\222\214\345\211\215\350\277\233.drawio"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204/\346\240\210\345\256\236\347\216\260\346\265\217\350\247\210\345\231\250\345\200\222\351\200\200\345\222\214\345\211\215\350\277\233.drawio"
rename to "docs/cs-basics/data-structure/pictures/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204/\346\240\210\345\256\236\347\216\260\346\265\217\350\247\210\345\231\250\345\200\222\351\200\200\345\222\214\345\211\215\350\277\233.drawio"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204/\346\240\210\345\256\236\347\216\260\346\265\217\350\247\210\345\231\250\345\200\222\351\200\200\345\222\214\345\211\215\350\277\233.png" "b/docs/cs-basics/data-structure/pictures/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204/\346\240\210\345\256\236\347\216\260\346\265\217\350\247\210\345\231\250\345\200\222\351\200\200\345\222\214\345\211\215\350\277\233.png"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204/\346\240\210\345\256\236\347\216\260\346\265\217\350\247\210\345\231\250\345\200\222\351\200\200\345\222\214\345\211\215\350\277\233.png"
rename to "docs/cs-basics/data-structure/pictures/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204/\346\240\210\345\256\236\347\216\260\346\265\217\350\247\210\345\231\250\345\200\222\351\200\200\345\222\214\345\211\215\350\277\233.png"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204/\351\230\237\345\210\227.png" "b/docs/cs-basics/data-structure/pictures/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204/\351\230\237\345\210\227.png"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204/\351\230\237\345\210\227.png"
rename to "docs/cs-basics/data-structure/pictures/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204/\351\230\237\345\210\227.png"
diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204/\351\241\272\345\272\217\351\230\237\345\210\227\345\201\207\346\272\242\345\207\272.png" "b/docs/cs-basics/data-structure/pictures/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204/\351\241\272\345\272\217\351\230\237\345\210\227\345\201\207\346\272\242\345\207\272.png"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/pictures/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204/\351\241\272\345\272\217\351\230\237\345\210\227\345\201\207\346\272\242\345\207\272.png"
rename to "docs/cs-basics/data-structure/pictures/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204/\351\241\272\345\272\217\351\230\237\345\210\227\345\201\207\346\272\242\345\207\272.png"
diff --git "a/docs/dataStructures-algorithms/data-structure/\345\233\276.md" "b/docs/cs-basics/data-structure/\345\233\276.md"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/\345\233\276.md"
rename to "docs/cs-basics/data-structure/\345\233\276.md"
diff --git "a/docs/dataStructures-algorithms/data-structure/\345\240\206.md" "b/docs/cs-basics/data-structure/\345\240\206.md"
similarity index 99%
rename from "docs/dataStructures-algorithms/data-structure/\345\240\206.md"
rename to "docs/cs-basics/data-structure/\345\240\206.md"
index 7e8f9811878..cd186132416 100644
--- "a/docs/dataStructures-algorithms/data-structure/\345\240\206.md"
+++ "b/docs/cs-basics/data-structure/\345\240\206.md"
@@ -1,4 +1,7 @@
+# 堆
+
## 什么是堆
+
堆是一种满足以下条件的树:
堆中的每一个节点值都大于等于(或小于等于)子树中所有节点的值。或者说,任意一个节点的值都大于等于(或小于等于)所有子节点的值。
diff --git "a/docs/cs-basics/data-structure/\346\240\221.md" "b/docs/cs-basics/data-structure/\346\240\221.md"
new file mode 100644
index 00000000000..010cff991ce
--- /dev/null
+++ "b/docs/cs-basics/data-structure/\346\240\221.md"
@@ -0,0 +1,174 @@
+# 树
+
+树就是一种类似现实生活中的树的数据结构(倒置的树)。任何一颗非空树只有一个根节点。
+
+一棵树具有以下特点:
+
+1. 一棵树中的任意两个结点有且仅有唯一的一条路径连通。
+2. 一棵树如果有 n 个结点,那么它一定恰好有 n-1 条边。
+3. 一棵树不包含回路。
+
+下图就是一颗树,并且是一颗二叉树。
+
+
+
+如上图所示,通过上面这张图说明一下树中的常用概念:
+
+- **节点** :树中的每个元素都可以统称为节点。
+- **根节点** :顶层节点或者说没有父节点的节点。上图中 A 节点就是根节点。
+- **父节点** :若一个节点含有子节点,则这个节点称为其子节点的父节点。上图中的 B 节点是 D 节点、E 节点的父节点。
+- **子节点** :一个节点含有的子树的根节点称为该节点的子节点。上图中 D 节点、E 节点是 B 节点的子节点。
+- **兄弟节点** :具有相同父节点的节点互称为兄弟节点。上图中 D 节点、E 节点的共同父节点是 B 节点,故 D 和 E 为兄弟节点。
+- **叶子节点** :没有子节点的节点。上图中的 D、F、H、I 都是叶子节点。
+- **节点的高度** :该节点到叶子节点的最长路径所包含的边数。
+- **节点的深度** :根节点到该节点的路径所包含的边数
+- **节点的层数** :节点的深度+1。
+- **树的高度** :根节点的高度。
+
+## 二叉树的分类
+
+**二叉树**(Binary tree)是每个节点最多只有两个分支(即不存在分支度大于 2 的节点)的树结构。
+
+**二叉树** 的分支通常被称作“**左子树**”或“**右子树**”。并且,**二叉树** 的分支具有左右次序,不能随意颠倒。
+
+**二叉树** 的第 i 层至多拥有 `2^(i-1)` 个节点,深度为 k 的二叉树至多总共有 `2^k-1` 个节点
+
+### 满二叉树
+
+一个二叉树,如果每一个层的结点数都达到最大值,则这个二叉树就是 **满二叉树**。也就是说,如果一个二叉树的层数为 K,且结点总数是(2^k) -1 ,则它就是 **满二叉树**。如下图所示:
+
+
+
+### 完全二叉树
+
+除最后一层外,若其余层都是满的,并且最后一层或者是满的,或者是在右边缺少连续若干节点,则这个二叉树就是 **完全二叉树** 。
+
+大家可以想象为一棵树从根结点开始扩展,扩展完左子节点才能开始扩展右子节点,每扩展完一层,才能继续扩展下一层。如下图所示:
+
+
+
+完全二叉树有一个很好的性质:**父结点和子节点的序号有着对应关系。**
+
+细心的小伙伴可能发现了,当根节点的值为 1 的情况下,若父结点的序号是 i,那么左子节点的序号就是 2i,右子节点的序号是 2i+1。这个性质使得完全二叉树利用数组存储时可以极大地节省空间,以及利用序号找到某个节点的父结点和子节点,后续二叉树的存储会详细介绍。
+
+### 平衡二叉树
+
+**平衡二叉树** 是一棵二叉排序树,且具有以下性质:
+
+1. 可以是一棵空树
+2. 如果不是空树,它的左右两个子树的高度差的绝对值不超过 1,并且左右两个子树都是一棵平衡二叉树。
+
+平衡二叉树的常用实现方法有 **红黑树**、**AVL 树**、**替罪羊树**、**加权平衡树**、**伸展树** 等。
+
+在给大家展示平衡二叉树之前,先给大家看一棵树:
+
+
+
+**你管这玩意儿叫树???**
+
+没错,这玩意儿还真叫树,只不过这棵树已经退化为一个链表了,我们管它叫 **斜树**。
+
+**如果这样,那我为啥不直接用链表呢?**
+
+谁说不是呢?
+
+二叉树相比于链表,由于父子节点以及兄弟节点之间往往具有某种特殊的关系,这种关系使得我们在树中对数据进行**搜索**和**修改**时,相对于链表更加快捷便利。
+
+但是,如果二叉树退化为一个链表了,那么那么树所具有的优秀性质就难以表现出来,效率也会大打折,为了避免这样的情况,我们希望每个做 “家长”(父结点) 的,都 **一碗水端平**,分给左儿子和分给右儿子的尽可能一样多,相差最多不超过一层,如下图所示:
+
+
+
+## 二叉树的存储
+
+二叉树的存储主要分为 **链式存储** 和 **顺序存储** 两种:
+
+### 链式存储
+
+和链表类似,二叉树的链式存储依靠指针将各个节点串联起来,不需要连续的存储空间。
+
+每个节点包括三个属性:
+
+- 数据 data。data 不一定是单一的数据,根据不同情况,可以是多个具有不同类型的数据。
+- 左节点指针 left
+- 右节点指针 right。
+
+可是 JAVA 没有指针啊!
+
+那就直接引用对象呗(别问我对象哪里找)
+
+
+
+### 顺序存储
+
+顺序存储就是利用数组进行存储,数组中的每一个位置仅存储节点的 data,不存储左右子节点的指针,子节点的索引通过数组下标完成。根结点的序号为 1,对于每个节点 Node,假设它存储在数组中下标为 i 的位置,那么它的左子节点就存储在 2 _ i 的位置,它的右子节点存储在下标为 2 _ i+1 的位置。
+
+一棵完全二叉树的数组顺序存储如下图所示:
+
+
+
+大家可以试着填写一下存储如下二叉树的数组,比较一下和完全二叉树的顺序存储有何区别:
+
+
+
+可以看到,如果我们要存储的二叉树不是完全二叉树,在数组中就会出现空隙,导致内存利用率降低
+
+## 二叉树的遍历
+
+### 先序遍历
+
+
+
+二叉树的先序遍历,就是先输出根结点,再遍历左子树,最后遍历右子树,遍历左子树和右子树的时候,同样遵循先序遍历的规则,也就是说,我们可以递归实现先序遍历。
+
+代码如下:
+
+```java
+public void preOrder(TreeNode root){
+ if(root == null){
+ return;
+ }
+ system.out.println(root.data);
+ preOrder(root.left);
+ preOrder(root.right);
+}
+```
+
+### 中序遍历
+
+
+
+二叉树的中序遍历,就是先递归中序遍历左子树,再输出根结点的值,再递归中序遍历右子树,大家可以想象成一巴掌把树压扁,父结点被拍到了左子节点和右子节点的中间,如下图所示:
+
+
+
+代码如下:
+
+```java
+public void inOrder(TreeNode root){
+ if(root == null){
+ return;
+ }
+ inOrder(root.left);
+ system.out.println(root.data);
+ inOrder(root.right);
+}
+```
+
+### 后序遍历
+
+
+
+二叉树的后序遍历,就是先递归后序遍历左子树,再递归后序遍历右子树,最后输出根结点的值
+
+代码如下:
+
+```java
+public void postOrder(TreeNode root){
+ if(root == null){
+ return;
+ }
+ postOrder(root.left);
+ postOrder(root.right);
+ system.out.println(root.data);
+}
+```
\ No newline at end of file
diff --git "a/docs/cs-basics/data-structure/\347\272\242\351\273\221\346\240\221.md" "b/docs/cs-basics/data-structure/\347\272\242\351\273\221\346\240\221.md"
new file mode 100644
index 00000000000..1f13744fa56
--- /dev/null
+++ "b/docs/cs-basics/data-structure/\347\272\242\351\273\221\346\240\221.md"
@@ -0,0 +1,14 @@
+**红黑树特点** :
+
+1. 每个节点非红即黑;
+2. 根节点总是黑色的;
+3. 每个叶子节点都是黑色的空节点(NIL节点);
+4. 如果节点是红色的,则它的子节点必须是黑色的(反之不一定);
+5. 从根节点到叶节点或空子节点的每条路径,必须包含相同数目的黑色节点(即相同的黑色高度)。
+
+**红黑树的应用** :TreeMap、TreeSet以及JDK1.8的HashMap底层都用到了红黑树。
+
+**为什么要用红黑树?** 简单来说红黑树就是为了解决二叉查找树的缺陷,因为二叉查找树在某些情况下会退化成一个线性结构。详细了解可以查看 [漫画:什么是红黑树?](https://juejin.im/post/5a27c6946fb9a04509096248#comment)(也介绍到了二叉查找树,非常推荐)
+
+**相关阅读** :[《红黑树深入剖析及Java实现》](https://zhuanlan.zhihu.com/p/24367771)(美团点评技术团队)
+
diff --git "a/docs/dataStructures-algorithms/data-structure/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204.md" "b/docs/cs-basics/data-structure/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204.md"
similarity index 100%
rename from "docs/dataStructures-algorithms/data-structure/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204.md"
rename to "docs/cs-basics/data-structure/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204.md"
diff --git "a/docs/network/HTTPS\344\270\255\347\232\204TLS.md" "b/docs/cs-basics/network/HTTPS\344\270\255\347\232\204TLS.md"
similarity index 100%
rename from "docs/network/HTTPS\344\270\255\347\232\204TLS.md"
rename to "docs/cs-basics/network/HTTPS\344\270\255\347\232\204TLS.md"
diff --git a/docs/network/images/Cut-Trough-Switching_0.gif b/docs/cs-basics/network/images/Cut-Trough-Switching_0.gif
similarity index 100%
rename from docs/network/images/Cut-Trough-Switching_0.gif
rename to docs/cs-basics/network/images/Cut-Trough-Switching_0.gif
diff --git a/docs/network/images/isp.png b/docs/cs-basics/network/images/isp.png
similarity index 100%
rename from docs/network/images/isp.png
rename to docs/cs-basics/network/images/isp.png
diff --git "a/docs/network/images/\344\270\203\345\261\202\344\275\223\347\263\273\347\273\223\346\236\204\345\233\276.png" "b/docs/cs-basics/network/images/\344\270\203\345\261\202\344\275\223\347\263\273\347\273\223\346\236\204\345\233\276.png"
similarity index 100%
rename from "docs/network/images/\344\270\203\345\261\202\344\275\223\347\263\273\347\273\223\346\236\204\345\233\276.png"
rename to "docs/cs-basics/network/images/\344\270\203\345\261\202\344\275\223\347\263\273\347\273\223\346\236\204\345\233\276.png"
diff --git "a/docs/network/images/\344\274\240\350\276\223\345\261\202.png" "b/docs/cs-basics/network/images/\344\274\240\350\276\223\345\261\202.png"
similarity index 100%
rename from "docs/network/images/\344\274\240\350\276\223\345\261\202.png"
rename to "docs/cs-basics/network/images/\344\274\240\350\276\223\345\261\202.png"
diff --git "a/docs/network/images/\345\272\224\347\224\250\345\261\202.png" "b/docs/cs-basics/network/images/\345\272\224\347\224\250\345\261\202.png"
similarity index 100%
rename from "docs/network/images/\345\272\224\347\224\250\345\261\202.png"
rename to "docs/cs-basics/network/images/\345\272\224\347\224\250\345\261\202.png"
diff --git "a/docs/network/images/\346\225\260\346\215\256\351\223\276\350\267\257\345\261\202.png" "b/docs/cs-basics/network/images/\346\225\260\346\215\256\351\223\276\350\267\257\345\261\202.png"
similarity index 100%
rename from "docs/network/images/\346\225\260\346\215\256\351\223\276\350\267\257\345\261\202.png"
rename to "docs/cs-basics/network/images/\346\225\260\346\215\256\351\223\276\350\267\257\345\261\202.png"
diff --git "a/docs/network/images/\347\211\251\347\220\206\345\261\202.png" "b/docs/cs-basics/network/images/\347\211\251\347\220\206\345\261\202.png"
similarity index 100%
rename from "docs/network/images/\347\211\251\347\220\206\345\261\202.png"
rename to "docs/cs-basics/network/images/\347\211\251\347\220\206\345\261\202.png"
diff --git "a/docs/network/images/\347\275\221\347\273\234\345\261\202.png" "b/docs/cs-basics/network/images/\347\275\221\347\273\234\345\261\202.png"
similarity index 100%
rename from "docs/network/images/\347\275\221\347\273\234\345\261\202.png"
rename to "docs/cs-basics/network/images/\347\275\221\347\273\234\345\261\202.png"
diff --git "a/docs/network/images/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\347\237\245\350\257\206\347\202\271\346\200\273\347\273\223/\344\270\207\347\273\264\347\275\221\347\232\204\345\244\247\350\207\264\345\267\245\344\275\234\345\267\245\347\250\213.png" "b/docs/cs-basics/network/images/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\347\237\245\350\257\206\347\202\271\346\200\273\347\273\223/\344\270\207\347\273\264\347\275\221\347\232\204\345\244\247\350\207\264\345\267\245\344\275\234\345\267\245\347\250\213.png"
similarity index 100%
rename from "docs/network/images/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\347\237\245\350\257\206\347\202\271\346\200\273\347\273\223/\344\270\207\347\273\264\347\275\221\347\232\204\345\244\247\350\207\264\345\267\245\344\275\234\345\267\245\347\250\213.png"
rename to "docs/cs-basics/network/images/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\347\237\245\350\257\206\347\202\271\346\200\273\347\273\223/\344\270\207\347\273\264\347\275\221\347\232\204\345\244\247\350\207\264\345\267\245\344\275\234\345\267\245\347\250\213.png"
diff --git "a/docs/network/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234.md" "b/docs/cs-basics/network/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234.md"
similarity index 100%
rename from "docs/network/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234.md"
rename to "docs/cs-basics/network/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234.md"
diff --git "a/docs/network/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\347\237\245\350\257\206\346\200\273\347\273\223.md" "b/docs/cs-basics/network/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\347\237\245\350\257\206\346\200\273\347\273\223.md"
similarity index 100%
rename from "docs/network/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\347\237\245\350\257\206\346\200\273\347\273\223.md"
rename to "docs/cs-basics/network/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\347\237\245\350\257\206\346\200\273\347\273\223.md"
diff --git a/docs/operating-system/Shell.md b/docs/cs-basics/operating-system/Shell.md
similarity index 100%
rename from docs/operating-system/Shell.md
rename to docs/cs-basics/operating-system/Shell.md
diff --git a/docs/operating-system/basis.md b/docs/cs-basics/operating-system/basis.md
similarity index 100%
rename from docs/operating-system/basis.md
rename to docs/cs-basics/operating-system/basis.md
diff --git a/docs/operating-system/images/Linux-Logo.png b/docs/cs-basics/operating-system/images/Linux-Logo.png
similarity index 100%
rename from docs/operating-system/images/Linux-Logo.png
rename to docs/cs-basics/operating-system/images/Linux-Logo.png
diff --git "a/docs/operating-system/images/Linux\344\271\213\347\210\266.png" "b/docs/cs-basics/operating-system/images/Linux\344\271\213\347\210\266.png"
similarity index 100%
rename from "docs/operating-system/images/Linux\344\271\213\347\210\266.png"
rename to "docs/cs-basics/operating-system/images/Linux\344\271\213\347\210\266.png"
diff --git "a/docs/operating-system/images/Linux\346\235\203\351\231\220\345\221\275\344\273\244.png" "b/docs/cs-basics/operating-system/images/Linux\346\235\203\351\231\220\345\221\275\344\273\244.png"
similarity index 100%
rename from "docs/operating-system/images/Linux\346\235\203\351\231\220\345\221\275\344\273\244.png"
rename to "docs/cs-basics/operating-system/images/Linux\346\235\203\351\231\220\345\221\275\344\273\244.png"
diff --git "a/docs/operating-system/images/Linux\346\235\203\351\231\220\350\247\243\350\257\273.png" "b/docs/cs-basics/operating-system/images/Linux\346\235\203\351\231\220\350\247\243\350\257\273.png"
similarity index 100%
rename from "docs/operating-system/images/Linux\346\235\203\351\231\220\350\247\243\350\257\273.png"
rename to "docs/cs-basics/operating-system/images/Linux\346\235\203\351\231\220\350\247\243\350\257\273.png"
diff --git "a/docs/operating-system/images/Linux\347\233\256\345\275\225\346\240\221.png" "b/docs/cs-basics/operating-system/images/Linux\347\233\256\345\275\225\346\240\221.png"
similarity index 100%
rename from "docs/operating-system/images/Linux\347\233\256\345\275\225\346\240\221.png"
rename to "docs/cs-basics/operating-system/images/Linux\347\233\256\345\275\225\346\240\221.png"
diff --git a/docs/operating-system/images/linux.png b/docs/cs-basics/operating-system/images/linux.png
similarity index 100%
rename from docs/operating-system/images/linux.png
rename to docs/cs-basics/operating-system/images/linux.png
diff --git a/docs/operating-system/images/macos.png b/docs/cs-basics/operating-system/images/macos.png
similarity index 100%
rename from docs/operating-system/images/macos.png
rename to docs/cs-basics/operating-system/images/macos.png
diff --git a/docs/operating-system/images/unix.png b/docs/cs-basics/operating-system/images/unix.png
similarity index 100%
rename from docs/operating-system/images/unix.png
rename to docs/cs-basics/operating-system/images/unix.png
diff --git a/docs/operating-system/images/windows.png b/docs/cs-basics/operating-system/images/windows.png
similarity index 100%
rename from docs/operating-system/images/windows.png
rename to docs/cs-basics/operating-system/images/windows.png
diff --git "a/docs/operating-system/images/\344\277\256\346\224\271\346\226\207\344\273\266\346\235\203\351\231\220.png" "b/docs/cs-basics/operating-system/images/\344\277\256\346\224\271\346\226\207\344\273\266\346\235\203\351\231\220.png"
similarity index 100%
rename from "docs/operating-system/images/\344\277\256\346\224\271\346\226\207\344\273\266\346\235\203\351\231\220.png"
rename to "docs/cs-basics/operating-system/images/\344\277\256\346\224\271\346\226\207\344\273\266\346\235\203\351\231\220.png"
diff --git "a/docs/operating-system/images/\346\226\207\344\273\266inode\344\277\241\346\201\257.png" "b/docs/cs-basics/operating-system/images/\346\226\207\344\273\266inode\344\277\241\346\201\257.png"
similarity index 100%
rename from "docs/operating-system/images/\346\226\207\344\273\266inode\344\277\241\346\201\257.png"
rename to "docs/cs-basics/operating-system/images/\346\226\207\344\273\266inode\344\277\241\346\201\257.png"
diff --git "a/docs/operating-system/images/\347\224\250\346\210\267\346\200\201\344\270\216\345\206\205\346\240\270\346\200\201.png" "b/docs/cs-basics/operating-system/images/\347\224\250\346\210\267\346\200\201\344\270\216\345\206\205\346\240\270\346\200\201.png"
similarity index 100%
rename from "docs/operating-system/images/\347\224\250\346\210\267\346\200\201\344\270\216\345\206\205\346\240\270\346\200\201.png"
rename to "docs/cs-basics/operating-system/images/\347\224\250\346\210\267\346\200\201\344\270\216\345\206\205\346\240\270\346\200\201.png"
diff --git a/docs/operating-system/linux.md b/docs/cs-basics/operating-system/linux.md
similarity index 100%
rename from docs/operating-system/linux.md
rename to docs/cs-basics/operating-system/linux.md
diff --git "a/docs/dataStructures-algorithms/\346\225\260\346\215\256\347\273\223\346\236\204.md" "b/docs/dataStructures-algorithms/\346\225\260\346\215\256\347\273\223\346\236\204.md"
deleted file mode 100644
index 5caffaac901..00000000000
--- "a/docs/dataStructures-algorithms/\346\225\260\346\215\256\347\273\223\346\236\204.md"
+++ /dev/null
@@ -1,179 +0,0 @@
-> 注意!!!这部分内容会进行重构,以下内容仅作为参考。
->
-
-- [Queue](#queue)
- - [什么是队列](#什么是队列)
- - [队列的种类](#队列的种类)
- - [Java 集合框架中的队列 Queue](#java-集合框架中的队列-queue)
- - [推荐文章](#推荐文章)
-- [Set](#set)
- - [什么是 Set](#什么是-set)
- - [补充:有序集合与无序集合说明](#补充:有序集合与无序集合说明)
- - [HashSet 和 TreeSet 底层数据结构](#hashset-和-treeset-底层数据结构)
- - [推荐文章](#推荐文章-1)
-- [List](#list)
- - [什么是List](#什么是list)
- - [List的常见实现类](#list的常见实现类)
- - [ArrayList 和 LinkedList 源码学习](#arraylist-和-linkedlist-源码学习)
- - [推荐阅读](#推荐阅读)
-- [Map](#map)
-- [树](#树)
-
-
-
-
-## Queue
-
-### 什么是队列
-队列是数据结构中比较重要的一种类型,它支持 FIFO,尾部添加、头部删除(先进队列的元素先出队列),跟我们生活中的排队类似。
-
-### 队列的种类
-
-- **单队列**(单队列就是常见的队列, 每次添加元素时,都是添加到队尾,存在“假溢出”的问题也就是明明有位置却不能添加的情况)
-- **循环队列**(避免了“假溢出”的问题)
-
-### Java 集合框架中的队列 Queue
-
-Java 集合中的 Queue 继承自 Collection 接口 ,Deque, LinkedList, PriorityQueue, BlockingQueue 等类都实现了它。
-Queue 用来存放 等待处理元素 的集合,这种场景一般用于缓冲、并发访问。
-除了继承 Collection 接口的一些方法,Queue 还添加了额外的 添加、删除、查询操作。
-
-## Set
-
-### 什么是 Set
-Set 继承于 Collection 接口,是一个不允许出现重复元素,并且无序的集合,主要 HashSet 和 TreeSet 两大实现类。
-
-在判断重复元素的时候,HashSet 集合会调用 hashCode()和 equal()方法来实现;TreeSet 集合会调用compareTo方法来实现。
-
-### 补充:有序集合与无序集合说明
-- 有序集合:集合里的元素可以根据 key 或 index 访问 (List、Map)
-- 无序集合:集合里的元素只能遍历。(Set)
-
-
-### HashSet 和 TreeSet 底层数据结构
-
-**HashSet** 是哈希表结构,主要利用 HashMap 的 key 来存储元素,计算插入元素的 hashCode 来获取元素在集合中的位置;
-
-**TreeSet** 是红黑树结构,每一个元素都是树中的一个节点,插入的元素都会进行排序;
-
-## List
-
-### 什么是List
-
-在 List 中,用户可以精确控制列表中每个元素的插入位置,另外用户可以通过整数索引(列表中的位置)访问元素,并搜索列表中的元素。 与 Set 不同,List 通常允许重复的元素。 另外 List 是有序集合而 Set 是无序集合。
-
-### List的常见实现类
-
-**ArrayList** 是一个数组队列,相当于动态数组。它由数组实现,随机访问效率高,随机插入、随机删除效率低。
-
-**LinkedList** 是一个双向链表。它也可以被当作堆栈、队列或双端队列进行操作。LinkedList随机访问效率低,但随机插入、随机删除效率高。
-
-**Vector** 是矢量队列,和ArrayList一样,它也是一个动态数组,由数组实现。但是ArrayList是非线程安全的,而Vector是线程安全的。
-
-**Stack** 是栈,它继承于Vector。它的特性是:先进后出(FILO, First In Last Out)。
-
-## 树
-
-### 1 二叉树
-
-[二叉树](https://baike.baidu.com/item/%E4%BA%8C%E5%8F%89%E6%A0%91)(百度百科)
-
-(1)[完全二叉树](https://baike.baidu.com/item/%E5%AE%8C%E5%85%A8%E4%BA%8C%E5%8F%89%E6%A0%91)——若设二叉树的高度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第h层有叶子结点,并且叶子结点都是从左到右依次排布,这就是完全二叉树。
-
-(2)[满二叉树](https://baike.baidu.com/item/%E6%BB%A1%E4%BA%8C%E5%8F%89%E6%A0%91)——除了叶结点外每一个结点都有左右子叶且叶子结点都处在最底层的二叉树。
-
-(3)[平衡二叉树](https://baike.baidu.com/item/%E5%B9%B3%E8%A1%A1%E4%BA%8C%E5%8F%89%E6%A0%91/10421057)——平衡二叉树又被称为AVL树(区别于AVL算法),它是一棵二叉排序树,且具有以下性质:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。
-
-### 2 完全二叉树
-
-[完全二叉树](https://baike.baidu.com/item/%E5%AE%8C%E5%85%A8%E4%BA%8C%E5%8F%89%E6%A0%91)(百度百科)
-
-完全二叉树:叶节点只能出现在最下层和次下层,并且最下面一层的结点都集中在该层最左边的若干位置的二叉树。
-
-### 3 满二叉树
-
-[满二叉树](https://baike.baidu.com/item/%E6%BB%A1%E4%BA%8C%E5%8F%89%E6%A0%91)(百度百科,国内外的定义不同)
-
-国内教程定义:一个二叉树,如果每一个层的结点数都达到最大值,则这个二叉树就是满二叉树。也就是说,如果一个二叉树的层数为K,且结点总数是(2^k) -1 ,则它就是满二叉树。
-
-### 堆
-
-[数据结构之堆的定义](https://blog.csdn.net/qq_33186366/article/details/51876191)
-
-堆是具有以下性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;或者每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆。
-
-### 4 二叉查找树(BST)
-
-[浅谈算法和数据结构: 七 二叉查找树](https://www.yycoding.xyz/post/2014/3/24/introduce-binary-search-tree)
-
-二叉查找树的特点:
-
-1. 若任意节点的左子树不空,则左子树上所有结点的 值均小于它的根结点的值;
-2. 若任意节点的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
-3. 任意节点的左、右子树也分别为二叉查找树;
-4. 没有键值相等的节点(no duplicate nodes)。
-
-### 5 平衡二叉树(Self-balancing binary search tree)
-
-[ 平衡二叉树](https://baike.baidu.com/item/%E5%B9%B3%E8%A1%A1%E4%BA%8C%E5%8F%89%E6%A0%91)(百度百科,平衡二叉树的常用实现方法有红黑树、AVL、替罪羊树、Treap、伸展树等)
-
-### 6 红黑树
-
-红黑树特点:
-
-1. 每个节点非红即黑;
-2. 根节点总是黑色的;
-3. 每个叶子节点都是黑色的空节点(NIL节点);
-4. 如果节点是红色的,则它的子节点必须是黑色的(反之不一定);
-5. 从根节点到叶节点或空子节点的每条路径,必须包含相同数目的黑色节点(即相同的黑色高度)。
-
-
-红黑树的应用:
-
-TreeMap、TreeSet以及JDK1.8的HashMap底层都用到了红黑树。
-
-**为什么要用红黑树?**
-
-
-简单来说红黑树就是为了解决二叉查找树的缺陷,因为二叉查找树在某些情况下会退化成一个线性结构。详细了解可以查看 [漫画:什么是红黑树?](https://juejin.im/post/5a27c6946fb9a04509096248#comment)(也介绍到了二叉查找树,非常推荐)
-
-推荐文章:
-
-- [漫画:什么是红黑树?](https://juejin.im/post/5a27c6946fb9a04509096248#comment)(也介绍到了二叉查找树,非常推荐)
-- [寻找红黑树的操作手册](http://dandanlove.com/2018/03/18/red-black-tree/)(文章排版以及思路真的不错)
-- [红黑树深入剖析及Java实现](https://zhuanlan.zhihu.com/p/24367771)(美团点评技术团队)
-
-### 7 B-,B+,B*树
-
-[二叉树学习笔记之B树、B+树、B*树 ](https://yq.aliyun.com/articles/38345)
-
-[《B-树,B+树,B*树详解》](https://blog.csdn.net/aqzwss/article/details/53074186)
-
-[《B-树,B+树与B*树的优缺点比较》](https://blog.csdn.net/bigtree_3721/article/details/73632405)
-
-B-树(或B树)是一种平衡的多路查找(又称排序)树,在文件系统中有所应用。主要用作文件的索引。其中的B就表示平衡(Balance)
-
-1. B+ 树的叶子节点链表结构相比于 B- 树便于扫库,和范围检索。
-2. B+树支持range-query(区间查询)非常方便,而B树不支持。这是数据库选用B+树的最主要原因。
-3. B\*树 是B+树的变体,B\*树分配新结点的概率比B+树要低,空间使用率更高;
-
-### 8 LSM 树
-
-[[HBase] LSM树 VS B+树](https://blog.csdn.net/dbanote/article/details/8897599)
-
-B+树最大的性能问题是会产生大量的随机IO
-
-为了克服B+树的弱点,HBase引入了LSM树的概念,即Log-Structured Merge-Trees。
-
-[LSM树由来、设计思想以及应用到HBase的索引](https://www.cnblogs.com/yanghuahui/p/3483754.html)
-
-
-## 图
-
-
-
-
-## BFS及DFS
-
-- [《使用BFS及DFS遍历树和图的思路及实现》](https://blog.csdn.net/Gene1994/article/details/85097507)
-
diff --git a/docs/database/Redis/redis-all.md b/docs/database/Redis/redis-all.md
index 64ea49d563a..93227374d2e 100644
--- a/docs/database/Redis/redis-all.md
+++ b/docs/database/Redis/redis-all.md
@@ -1,45 +1,5 @@
-点击关注[公众号](#公众号)及时获取笔主最新更新文章,并可免费领取本文档配套的《Java 面试突击》以及 Java 工程师必备学习资源。
-
-
-
-
-
-- [1. 简单介绍一下 Redis 呗!](#1-简单介绍一下-redis-呗)
-- [2. 分布式缓存常见的技术选型方案有哪些?](#2-分布式缓存常见的技术选型方案有哪些)
-- [3. 说一下 Redis 和 Memcached 的区别和共同点](#3-说一下-redis-和-memcached-的区别和共同点)
-- [4. 缓存数据的处理流程是怎样的?](#4-缓存数据的处理流程是怎样的)
-- [5. 为什么要用 Redis/为什么要用缓存?](#5-为什么要用-redis为什么要用缓存)
-- [6. Redis 常见数据结构以及使用场景分析](#6-redis-常见数据结构以及使用场景分析)
- - [6.1. string](#61-string)
- - [6.2. list](#62-list)
- - [6.3. hash](#63-hash)
- - [6.4. set](#64-set)
- - [6.5. sorted set](#65-sorted-set)
- - [6.6 bitmap](#66-bitmap)
-- [7. Redis 单线程模型详解](#7-redis-单线程模型详解)
-- [8. Redis 没有使用多线程?为什么不使用多线程?](#8-redis-没有使用多线程为什么不使用多线程)
-- [9. Redis6.0 之后为何引入了多线程?](#9-redis60-之后为何引入了多线程)
-- [10. Redis 给缓存数据设置过期时间有啥用?](#10-redis-给缓存数据设置过期时间有啥用)
-- [11. Redis 是如何判断数据是否过期的呢?](#11-redis-是如何判断数据是否过期的呢)
-- [12. 过期的数据的删除策略了解么?](#12-过期的数据的删除策略了解么)
-- [13. Redis 内存淘汰机制了解么?](#13-redis-内存淘汰机制了解么)
-- [14. Redis 持久化机制(怎么保证 Redis 挂掉之后再重启数据可以进行恢复)](#14-redis-持久化机制怎么保证-redis-挂掉之后再重启数据可以进行恢复)
-- [15. Redis 事务](#15-redis-事务)
-- [16. 缓存穿透](#16-缓存穿透)
- - [16.1. 什么是缓存穿透?](#161-什么是缓存穿透)
- - [16.2. 缓存穿透情况的处理流程是怎样的?](#162-缓存穿透情况的处理流程是怎样的)
- - [16.3. 有哪些解决办法?](#163-有哪些解决办法)
-- [17. 缓存雪崩](#17-缓存雪崩)
- - [17.1. 什么是缓存雪崩?](#171-什么是缓存雪崩)
- - [17.2. 有哪些解决办法?](#172-有哪些解决办法)
-- [18. 如何保证缓存和数据库数据的一致性?](#18-如何保证缓存和数据库数据的一致性)
-- [19. 参考](#19-参考)
-- [20. 公众号](#20-公众号)
-
-
-
-
-### 1. 简单介绍一下 Redis 呗!
+
+### 简单介绍一下 Redis 呗!
简单来说 **Redis 就是一个使用 C 语言开发的数据库**,不过与传统数据库不同的是 **Redis 的数据是存在内存中的** ,也就是它是内存数据库,所以读写速度非常快,因此 Redis 被广泛应用于缓存方向。
@@ -47,7 +7,7 @@
**Redis 提供了多种数据类型来支持不同的业务场景。Redis 还支持事务 、持久化、Lua 脚本、多种集群方案。**
-### 2. 分布式缓存常见的技术选型方案有哪些?
+### 分布式缓存常见的技术选型方案有哪些?
分布式缓存的话,使用的比较多的主要是 **Memcached** 和 **Redis**。不过,现在基本没有看过还有项目使用 **Memcached** 来做缓存,都是直接用 **Redis**。
@@ -55,7 +15,7 @@ Memcached 是分布式缓存最开始兴起的那会,比较常用的。后来
分布式缓存主要解决的是单机缓存的容量受服务器限制并且无法保存通用信息的问题。因为,本地缓存只在当前服务里有效,比如如果你部署了两个相同的服务,他们两者之间的缓存数据是无法共同的。
-### 3. 说一下 Redis 和 Memcached 的区别和共同点
+### 说一下 Redis 和 Memcached 的区别和共同点
现在公司一般都是用 Redis 来实现缓存,而且 Redis 自身也越来越强大了!不过,了解 Redis 和 Memcached 的区别和共同点,有助于我们在做相应的技术选型的时候,能够做到有理有据!
@@ -78,7 +38,7 @@ Memcached 是分布式缓存最开始兴起的那会,比较常用的。后来
相信看了上面的对比之后,我们已经没有什么理由可以选择使用 Memcached 来作为自己项目的分布式缓存了。
-### 4. 缓存数据的处理流程是怎样的?
+### 缓存数据的处理流程是怎样的?
作为暖男一号,我给大家画了一个草图。
@@ -91,7 +51,7 @@ Memcached 是分布式缓存最开始兴起的那会,比较常用的。后来
3. 数据库中存在的话就更新缓存中的数据。
4. 数据库中不存在的话就返回空数据。
-### 5. 为什么要用 Redis/为什么要用缓存?
+### 为什么要用 Redis/为什么要用缓存?
_简单,来说使用缓存主要是为了提升用户体验以及应对更多的用户。_
@@ -117,13 +77,21 @@ _简单,来说使用缓存主要是为了提升用户体验以及应对更多
由此可见,直接操作缓存能够承受的数据库请求数量是远远大于直接访问数据库的,所以我们可以考虑把数据库中的部分数据转移到缓存中去,这样用户的一部分请求会直接到缓存这里而不用经过数据库。进而,我们也就提高了系统整体的并发。
-### 6. Redis 常见数据结构以及使用场景分析
+### Redis 除了做缓存,还能做什么?
+
+- **分布式锁** : 通过 Redis 来做分布式锁是一种比较常见的方式。通常情况下,我们都是基于 Redisson 来实现分布式锁。相关阅读:[《分布式锁中的王者方案 - Redisson》](https://mp.weixin.qq.com/s/CbnPRfvq4m1sqo2uKI6qQw)。
+- **限流** :一般是通过 Redis + Lua 脚本的方式来实现限流。相关阅读:[《我司用了 6 年的 Redis 分布式限流器,可以说是非常厉害了!》](https://mp.weixin.qq.com/s/kyFAWH3mVNJvurQDt4vchA)。
+- **消息队列** :Redis 自带的 list 数据结构可以作为一个简单的队列使用。Redis5.0 中增加的 Stream 类型的数据结构更加适合用来做消息队列。它比较类似于 Kafka,有主题和消费组的概念,支持消息持久化以及 ACK 机制。
+- **复杂业务场景** :通过 Redis 以及 Redis 扩展(比如 Redisson)提供的数据结构,我们可以很方便地完成很多复杂的业务场景比如通过 bitmap 统计活跃用户、通过 sorted set 维护排行榜。
+- ......
+
+### Redis 常见数据结构以及使用场景分析
你可以自己本机安装 redis 或者通过 redis 官网提供的[在线 redis 环境](https://try.redis.io/)。

-#### 6.1. string
+#### string
1. **介绍** :string 数据结构是简单的 key-value 类型。虽然 Redis 是用 C 语言写的,但是 Redis 并没有使用 C 的字符串表示,而是自己构建了一种 **简单动态字符串**(simple dynamic string,**SDS**)。相比于 C 的原生字符串,Redis 的 SDS 不光可以保存文本数据还可以保存二进制数据,并且获取字符串长度复杂度为 O(1)(C 字符串为 O(N)),除此之外,Redis 的 SDS API 是安全的,不会造成缓冲区溢出。
2. **常用命令:** `set,get,strlen,exists,decr,incr,setex` 等等。
@@ -184,7 +152,7 @@ OK
(integer) 56
```
-#### 6.2. list
+#### list
1. **介绍** :**list** 即是 **链表**。链表是一种非常常见的数据结构,特点是易于数据元素的插入和删除并且可以灵活调整链表长度,但是链表的随机访问困难。许多高级编程语言都内置了链表的实现比如 Java 中的 **LinkedList**,但是 C 语言并没有实现链表,所以 Redis 实现了自己的链表数据结构。Redis 的 list 的实现为一个 **双向链表**,即可以支持反向查找和遍历,更方便操作,不过带来了部分额外的内存开销。
2. **常用命令:** `rpush,lpop,lpush,rpop,lrange,llen` 等。
@@ -245,7 +213,7 @@ OK
(integer) 3
```
-#### 6.3. hash
+#### hash
1. **介绍** :hash 类似于 JDK1.8 前的 HashMap,内部实现也差不多(数组 + 链表)。不过,Redis 的 hash 做了更多优化。另外,hash 是一个 string 类型的 field 和 value 的映射表,**特别适合用于存储对象**,后续操作的时候,你可以直接仅仅修改这个对象中的某个字段的值。 比如我们可以 hash 数据结构来存储用户信息,商品信息等等。
2. **常用命令:** `hset,hmset,hexists,hget,hgetall,hkeys,hvals` 等。
@@ -282,7 +250,7 @@ OK
"GuideGeGe"
```
-#### 6.4. set
+#### set
1. **介绍 :** set 类似于 Java 中的 `HashSet` 。Redis 中的 set 类型是一种无序集合,集合中的元素没有先后顺序。当你需要存储一个列表数据,又不希望出现重复数据时,set 是一个很好的选择,并且 set 提供了判断某个成员是否在一个 set 集合内的重要接口,这个也是 list 所不能提供的。可以基于 set 轻易实现交集、并集、差集的操作。比如:你可以将一个用户所有的关注人存在一个集合中,将其所有粉丝存在一个集合。Redis 可以非常方便的实现如共同关注、共同粉丝、共同喜好等功能。这个过程也就是求交集的过程。
2. **常用命令:** `sadd,spop,smembers,sismember,scard,sinterstore,sunion` 等。
@@ -310,7 +278,7 @@ OK
1) "value2"
```
-#### 6.5. sorted set
+#### sorted set
1. **介绍:** 和 set 相比,sorted set 增加了一个权重参数 score,使得集合中的元素能够按 score 进行有序排列,还可以通过 score 的范围来获取元素的列表。有点像是 Java 中 HashMap 和 TreeSet 的结合体。
2. **常用命令:** `zadd,zcard,zscore,zrange,zrevrange,zrem` 等。
@@ -337,7 +305,7 @@ OK
2) "value2"
```
-#### 6.6 bitmap
+#### bitmap
1. **介绍:** bitmap 存储的是连续的二进制数字(0 和 1),通过 bitmap, 只需要一个 bit 位来表示某个元素对应的值或者状态,key 就是对应元素本身 。我们知道 8 个 bit 可以组成一个 byte,所以 bitmap 本身会极大的节省储存空间。
2. **常用命令:** `setbit` 、`getbit` 、`bitcount`、`bitop`
@@ -417,7 +385,7 @@ BITOP operation destkey key [key ...]
只需要一个 key,然后用户 ID 为 offset,如果在线就设置为 1,不在线就设置为 0。
-### 7. Redis 单线程模型详解
+### Redis 单线程模型详解
**Redis 基于 Reactor 模式来设计开发了自己的一套高效的事件处理模型** (Netty 的线程模型也基于 Reactor 模式,Reactor 模式不愧是高性能 IO 的基石),这套事件处理模型对应的是 Redis 中的文件事件处理器(file event handler)。由于文件事件处理器(file event handler)是单线程方式运行的,所以我们一般都说 Redis 是单线程模型。
@@ -450,7 +418,7 @@ Redis 通过**IO 多路复用程序** 来监听来自客户端的大量连接(
《Redis设计与实现:12章》
-### 8. Redis 没有使用多线程?为什么不使用多线程?
+### Redis 没有使用多线程?为什么不使用多线程?
虽然说 Redis 是单线程模型,但是,实际上,**Redis 在 4.0 之后的版本中就已经加入了对多线程的支持。**
@@ -468,7 +436,7 @@ Redis 通过**IO 多路复用程序** 来监听来自客户端的大量连接(
2. Redis 的性能瓶颈不在 CPU ,主要在内存和网络;
3. 多线程就会存在死锁、线程上下文切换等问题,甚至会影响性能。
-### 9. Redis6.0 之后为何引入了多线程?
+### Redis6.0 之后为何引入了多线程?
**Redis6.0 引入多线程主要是为了提高网络 IO 读写性能**,因为这个算是 Redis 中的一个性能瓶颈(Redis 的瓶颈主要受限于内存和网络)。
@@ -491,7 +459,7 @@ io-threads 4 #官网建议4核的机器建议设置为2或3个线程,8核的
1. [Redis 6.0 新特性-多线程连环 13 问!](https://mp.weixin.qq.com/s/FZu3acwK6zrCBZQ_3HoUgw)
2. [为什么 Redis 选择单线程模型](https://draveness.me/whys-the-design-redis-single-thread/)
-### 10. Redis 给缓存数据设置过期时间有啥用?
+### Redis 给缓存数据设置过期时间有啥用?
一般情况下,我们设置保存的缓存数据的时候都会设置一个过期时间。为什么呢?
@@ -516,7 +484,7 @@ OK
如果使用传统的数据库来处理的话,一般都是自己判断过期,这样更麻烦并且性能要差很多。
-### 11. Redis 是如何判断数据是否过期的呢?
+### Redis 是如何判断数据是否过期的呢?
Redis 通过一个叫做过期字典(可以看作是 hash 表)来保存数据过期的时间。过期字典的键指向 Redis 数据库中的某个 key(键),过期字典的值是一个 long long 类型的整数,这个整数保存了 key 所指向的数据库键的过期时间(毫秒精度的 UNIX 时间戳)。
@@ -534,7 +502,7 @@ typedef struct redisDb {
} redisDb;
```
-### 12. 过期的数据的删除策略了解么?
+### 过期的数据的删除策略了解么?
如果假设你设置了一批 key 只能存活 1 分钟,那么 1 分钟后,Redis 是怎么对这批 key 进行删除的呢?
@@ -549,7 +517,7 @@ typedef struct redisDb {
怎么解决这个问题呢?答案就是:**Redis 内存淘汰机制。**
-### 13. Redis 内存淘汰机制了解么?
+### Redis 内存淘汰机制了解么?
> 相关问题:MySQL 里有 2000w 数据,Redis 中只存 20w 的数据,如何保证 Redis 中的数据都是热点数据?
@@ -567,7 +535,7 @@ Redis 提供 6 种数据淘汰策略:
7. **volatile-lfu(least frequently used)**:从已设置过期时间的数据集(server.db[i].expires)中挑选最不经常使用的数据淘汰
8. **allkeys-lfu(least frequently used)**:当内存不足以容纳新写入数据时,在键空间中,移除最不经常使用的 key
-### 14. Redis 持久化机制(怎么保证 Redis 挂掉之后再重启数据可以进行恢复)
+### Redis 持久化机制(怎么保证 Redis 挂掉之后再重启数据可以进行恢复)
很多时候我们需要持久化数据也就是将内存中的数据写入到硬盘里面,大部分原因是为了之后重用数据(比如重启机器、机器故障之后恢复数据),或者是为了防止系统故障而将数据备份到一个远程位置。
@@ -629,7 +597,7 @@ AOF 重写是一个有歧义的名字,该功能是通过读取数据库中的
在执行 BGREWRITEAOF 命令时,Redis 服务器会维护一个 AOF 重写缓冲区,该缓冲区会在子进程创建新 AOF 文件期间,记录服务器执行的所有写命令。当子进程完成创建新 AOF 文件的工作之后,服务器会将重写缓冲区中的所有内容追加到新 AOF 文件的末尾,使得新旧两个 AOF 文件所保存的数据库状态一致。最后,服务器用新的 AOF 文件替换旧的 AOF 文件,以此来完成 AOF 文件重写操作。
-### 15. Redis 事务
+### Redis 事务
Redis 可以通过 **`MULTI`,`EXEC`,`DISCARD` 和 `WATCH`** 等命令来实现事务(transaction)功能。
@@ -704,19 +672,19 @@ Redis 官网也解释了自己为啥不支持回滚。简单来说就是 Redis
- [issue452: 关于 Redis 事务不满足原子性的问题](https://github.com/Snailclimb/JavaGuide/issues/452) 。
- [Issue491:关于 redis 没有事务回滚?](https://github.com/Snailclimb/JavaGuide/issues/491)
-### 16. 缓存穿透
+### 缓存穿透
-#### 16.1. 什么是缓存穿透?
+#### 什么是缓存穿透?
缓存穿透说简单点就是大量请求的 key 根本不存在于缓存中,导致请求直接到了数据库上,根本没有经过缓存这一层。举个例子:某个黑客故意制造我们缓存中不存在的 key 发起大量请求,导致大量请求落到数据库。
-#### 16.2. 缓存穿透情况的处理流程是怎样的?
+#### 缓存穿透情况的处理流程是怎样的?
如下图所示,用户的请求最终都要跑到数据库中查询一遍。

-#### 16.3. 有哪些解决办法?
+#### 有哪些解决办法?
最基本的就是首先做好参数校验,一些不合法的参数请求直接抛出异常信息返回给客户端。比如查询的数据库 id 不能小于 0、传入的邮箱格式不对的时候直接返回错误消息给客户端等等。
@@ -777,9 +745,9 @@ _为什么会出现误判的情况呢? 我们还要从布隆过滤器的原理
更多关于布隆过滤器的内容可以看我的这篇原创:[《不了解布隆过滤器?一文给你整的明明白白!》](https://github.com/Snailclimb/JavaGuide/blob/master/docs/dataStructures-algorithms/data-structure/bloom-filter.md) ,强烈推荐,个人感觉网上应该找不到总结的这么明明白白的文章了。
-### 17. 缓存雪崩
+### 缓存雪崩
-#### 17.1. 什么是缓存雪崩?
+#### 什么是缓存雪崩?
我发现缓存雪崩这名字起的有点意思,哈哈。
@@ -791,7 +759,7 @@ _为什么会出现误判的情况呢? 我们还要从布隆过滤器的原理
举个例子 :秒杀开始 12 个小时之前,我们统一存放了一批商品到 Redis 中,设置的缓存过期时间也是 12 个小时,那么秒杀开始的时候,这些秒杀的商品的访问直接就失效了。导致的情况就是,相应的请求直接就落到了数据库上,就像雪崩一样可怕。
-#### 17.2. 有哪些解决办法?
+#### 有哪些解决办法?
**针对 Redis 服务不可用的情况:**
@@ -803,7 +771,7 @@ _为什么会出现误判的情况呢? 我们还要从布隆过滤器的原理
1. 设置不同的失效时间比如随机设置缓存的失效时间。
2. 缓存永不失效。
-### 18. 如何保证缓存和数据库数据的一致性?
+### 如何保证缓存和数据库数据的一致性?
细说的话可以扯很多,但是我觉得其实没太大必要(小声 BB:很多解决方案我也没太弄明白)。我个人觉得引入缓存之后,如果为了短时间的不一致性问题,选择让系统设计变得更加复杂的话,完全没必要。
@@ -816,20 +784,10 @@ Cache Aside Pattern 中遇到写请求是这样的:更新 DB,然后直接删
1. **缓存失效时间变短(不推荐,治标不治本)** :我们让缓存数据的过期时间变短,这样的话缓存就会从数据库中加载数据。另外,这种解决办法对于先操作缓存后操作数据库的场景不适用。
2. **增加 cache 更新重试机制(常用)**: 如果 cache 服务当前不可用导致缓存删除失败的话,我们就隔一段时间进行重试,重试次数可以自己定。如果多次重试还是失败的话,我们可以把当前更新失败的 key 存入队列中,等缓存服务可用之后,再将缓存中对应的 key 删除即可。
-### 19. 参考
+### 参考
- 《Redis 开发与运维》
- 《Redis 设计与实现》
- Redis 命令总结:http://Redisdoc.com/string/set.html
- 通俗易懂的 Redis 数据结构基础教程:[https://juejin.im/post/5b53ee7e5188251aaa2d2e16](https://juejin.im/post/5b53ee7e5188251aaa2d2e16)
- WHY Redis choose single thread (vs multi threads): [https://medium.com/@jychen7/sharing-redis-single-thread-vs-multi-threads-5870bd44d153](https://medium.com/@jychen7/sharing-redis-single-thread-vs-multi-threads-5870bd44d153)
-
-### 20. 公众号
-
-如果大家想要实时关注我更新的文章以及分享的干货的话,可以关注我的公众号。
-
-**《Java 面试突击》:** 由本文档衍生的专为面试而生的《Java 面试突击》V2.0 PDF 版本[公众号](#公众号)后台回复 **"Java 面试突击"** 即可免费领取!
-
-**Java 工程师必备学习资源:** 一些 Java 工程师常用学习资源公众号后台回复关键字 **“1”** 即可免费无套路获取。
-
-
\ No newline at end of file
diff --git "a/docs/database/mysql/MySQL\344\270\211\345\244\247\346\227\245\345\277\227(binlog\343\200\201redo log\345\222\214undo log).md" "b/docs/database/mysql/MySQL\344\270\211\345\244\247\346\227\245\345\277\227(binlog\343\200\201redo log\345\222\214undo log).md"
new file mode 100644
index 00000000000..616fab71874
--- /dev/null
+++ "b/docs/database/mysql/MySQL\344\270\211\345\244\247\346\227\245\345\277\227(binlog\343\200\201redo log\345\222\214undo log).md"
@@ -0,0 +1,280 @@
+> 本文来自公号程序猿阿星投稿,JavaGuide 对其做了补充完善。
+
+## 前言
+
+`MySQL` 日志 主要包括错误日志、查询日志、慢查询日志、事务日志、二进制日志几大类。其中,比较重要的还要属二进制日志 `binlog`(归档日志)和事务日志 `redo log`(重做日志)和 `undo log`(回滚日志)。
+
+
+
+今天就来聊聊 `redo log`(重做日志)、`binlog`(归档日志)、两阶段提交、`undo log` (回滚日志)。
+
+## redo log
+
+`redo log`(重做日志)是`InnoDB`存储引擎独有的,它让`MySQL`拥有了崩溃恢复能力。
+
+比如 `MySQL` 实例挂了或宕机了,重启时,`InnoDB`存储引擎会使用`redo log`恢复数据,保证数据的持久性与完整性。
+
+
+
+`MySQL` 中数据是以页为单位,你查询一条记录,会从硬盘把一页的数据加载出来,加载出来的数据叫数据页,会放入到 `Buffer Pool` 中。
+
+后续的查询都是先从 `Buffer Pool` 中找,没有命中再去硬盘加载,减少硬盘 `IO` 开销,提升性能。
+
+更新表数据的时候,也是如此,发现 `Buffer Pool` 里存在要更新的数据,就直接在 `Buffer Pool` 里更新。
+
+然后会把“在某个数据页上做了什么修改”记录到重做日志缓存(`redo log buffer`)里,接着刷盘到 `redo log` 文件里。
+
+
+
+理想情况,事务一提交就会进行刷盘操作,但实际上,刷盘的时机是根据策略来进行的。
+
+> 小贴士:每条 redo 记录由“表空间号+数据页号+偏移量+修改数据长度+具体修改的数据”组成
+
+### 刷盘时机
+
+`InnoDB` 存储引擎为 `redo log` 的刷盘策略提供了 `innodb_flush_log_at_trx_commit` 参数,它支持三种策略:
+
+- **0** :设置为 0 的时候,表示每次事务提交时不进行刷盘操作
+- **1** :设置为 1 的时候,表示每次事务提交时都将进行刷盘操作(默认值)
+- **2** :设置为 2 的时候,表示每次事务提交时都只把 redo log buffer 内容写入 page cache
+
+`innodb_flush_log_at_trx_commit` 参数默认为 1 ,也就是说当事务提交时会调用 `fsync` 对 redo log 进行刷盘
+
+另外,`InnoDB` 存储引擎有一个后台线程,每隔`1` 秒,就会把 `redo log buffer` 中的内容写到文件系统缓存(`page cache`),然后调用 `fsync` 刷盘。
+
+
+
+也就是说,一个没有提交事务的 `redo log` 记录,也可能会刷盘。
+
+**为什么呢?**
+
+因为在事务执行过程 `redo log` 记录是会写入`redo log buffer` 中,这些 `redo log` 记录会被后台线程刷盘。
+
+
+
+除了后台线程每秒`1`次的轮询操作,还有一种情况,当 `redo log buffer` 占用的空间即将达到 `innodb_log_buffer_size` 一半的时候,后台线程会主动刷盘。
+
+下面是不同刷盘策略的流程图。
+
+#### innodb_flush_log_at_trx_commit=0
+
+
+
+为`0`时,如果`MySQL`挂了或宕机可能会有`1`秒数据的丢失。
+
+#### innodb_flush_log_at_trx_commit=1
+
+
+
+为`1`时, 只要事务提交成功,`redo log`记录就一定在硬盘里,不会有任何数据丢失。
+
+如果事务执行期间`MySQL`挂了或宕机,这部分日志丢了,但是事务并没有提交,所以日志丢了也不会有损失。
+
+#### innodb_flush_log_at_trx_commit=2
+
+
+
+为`2`时, 只要事务提交成功,`redo log buffer`中的内容只写入文件系统缓存(`page cache`)。
+
+如果仅仅只是`MySQL`挂了不会有任何数据丢失,但是宕机可能会有`1`秒数据的丢失。
+
+### 日志文件组
+
+硬盘上存储的 `redo log` 日志文件不只一个,而是以一个**日志文件组**的形式出现的,每个的`redo`日志文件大小都是一样的。
+
+比如可以配置为一组`4`个文件,每个文件的大小是 `1GB`,整个 `redo log` 日志文件组可以记录`4G`的内容。
+
+它采用的是环形数组形式,从头开始写,写到末尾又回到头循环写,如下图所示。
+
+
+
+在个**日志文件组**中还有两个重要的属性,分别是 `write pos、checkpoint`
+
+- **write pos** 是当前记录的位置,一边写一边后移
+- **checkpoint** 是当前要擦除的位置,也是往后推移
+
+每次刷盘 `redo log` 记录到**日志文件组**中,`write pos` 位置就会后移更新。
+
+每次 `MySQL` 加载**日志文件组**恢复数据时,会清空加载过的 `redo log` 记录,并把 `checkpoint` 后移更新。
+
+`write pos` 和 `checkpoint` 之间的还空着的部分可以用来写入新的 `redo log` 记录。
+
+
+
+如果 `write pos` 追上 `checkpoint` ,表示**日志文件组**满了,这时候不能再写入新的 `redo log` 记录,`MySQL` 得停下来,清空一些记录,把 `checkpoint` 推进一下。
+
+
+
+### redo log 小结
+
+相信大家都知道 `redo log` 的作用和它的刷盘时机、存储形式。
+
+现在我们来思考一个问题: **只要每次把修改后的数据页直接刷盘不就好了,还有 `redo log` 什么事?**
+
+它们不都是刷盘么?差别在哪里?
+
+```java
+1 Byte = 8bit
+1 KB = 1024 Byte
+1 MB = 1024 KB
+1 GB = 1024 MB
+1 TB = 1024 GB
+```
+
+实际上,数据页大小是`16KB`,刷盘比较耗时,可能就修改了数据页里的几 `Byte` 数据,有必要把完整的数据页刷盘吗?
+
+而且数据页刷盘是随机写,因为一个数据页对应的位置可能在硬盘文件的随机位置,所以性能是很差。
+
+如果是写 `redo log`,一行记录可能就占几十 `Byte`,只包含表空间号、数据页号、磁盘文件偏移
+量、更新值,再加上是顺序写,所以刷盘速度很快。
+
+所以用 `redo log` 形式记录修改内容,性能会远远超过刷数据页的方式,这也让数据库的并发能力更强。
+
+> 其实内存的数据页在一定时机也会刷盘,我们把这称为页合并,讲 `Buffer Pool`的时候会对这块细说
+
+## binlog
+
+`redo log` 它是物理日志,记录内容是“在某个数据页上做了什么修改”,属于 `InnoDB` 存储引擎。
+
+而 `binlog` 是逻辑日志,记录内容是语句的原始逻辑,类似于“给 ID=2 这一行的 c 字段加 1”,属于`MySQL Server` 层。
+
+不管用什么存储引擎,只要发生了表数据更新,都会产生 `binlog` 日志。
+
+那 `binlog` 到底是用来干嘛的?
+
+可以说`MySQL`数据库的**数据备份、主备、主主、主从**都离不开`binlog`,需要依靠`binlog`来同步数据,保证数据一致性。
+
+
+
+`binlog`会记录所有涉及更新数据的逻辑操作,并且是顺序写。
+
+### 记录格式
+
+`binlog` 日志有三种格式,可以通过`binlog_format`参数指定。
+
+- **statement**
+- **row**
+- **mixed**
+
+指定`statement`,记录的内容是`SQL`语句原文,比如执行一条`update T set update_time=now() where id=1`,记录的内容如下。
+
+
+
+同步数据时,会执行记录的`SQL`语句,但是有个问题,`update_time=now()`这里会获取当前系统时间,直接执行会导致与原库的数据不一致。
+
+为了解决这种问题,我们需要指定为`row`,记录的内容不再是简单的`SQL`语句了,还包含操作的具体数据,记录内容如下。
+
+
+
+`row`格式记录的内容看不到详细信息,要通过`mysqlbinlog`工具解析出来。
+
+`update_time=now()`变成了具体的时间`update_time=1627112756247`,条件后面的@1、@2、@3 都是该行数据第 1 个~3 个字段的原始值(**假设这张表只有 3 个字段**)。
+
+这样就能保证同步数据的一致性,通常情况下都是指定为`row`,这样可以为数据库的恢复与同步带来更好的可靠性。
+
+但是这种格式,需要更大的容量来记录,比较占用空间,恢复与同步时会更消耗`IO`资源,影响执行速度。
+
+所以就有了一种折中的方案,指定为`mixed`,记录的内容是前两者的混合。
+
+`MySQL`会判断这条`SQL`语句是否可能引起数据不一致,如果是,就用`row`格式,否则就用`statement`格式。
+
+### 写入机制
+
+`binlog`的写入时机也非常简单,事务执行过程中,先把日志写到`binlog cache`,事务提交的时候,再把`binlog cache`写到`binlog`文件中。
+
+因为一个事务的`binlog`不能被拆开,无论这个事务多大,也要确保一次性写入,所以系统会给每个线程分配一个块内存作为`binlog cache`。
+
+我们可以通过`binlog_cache_size`参数控制单个线程 binlog cache 大小,如果存储内容超过了这个参数,就要暂存到磁盘(`Swap`)。
+
+`binlog`日志刷盘流程如下
+
+
+
+- **上图的 write,是指把日志写入到文件系统的 page cache,并没有把数据持久化到磁盘,所以速度比较快**
+- **上图的 fsync,才是将数据持久化到磁盘的操作**
+
+`write`和`fsync`的时机,可以由参数`sync_binlog`控制,默认是`0`。
+
+为`0`的时候,表示每次提交事务都只`write`,由系统自行判断什么时候执行`fsync`。
+
+
+
+虽然性能得到提升,但是机器宕机,`page cache`里面的 binglog 会丢失。
+
+为了安全起见,可以设置为`1`,表示每次提交事务都会执行`fsync`,就如同**binlog 日志刷盘流程**一样。
+
+最后还有一种折中方式,可以设置为`N(N>1)`,表示每次提交事务都`write`,但累积`N`个事务后才`fsync`。
+
+
+
+在出现`IO`瓶颈的场景里,将`sync_binlog`设置成一个比较大的值,可以提升性能。
+
+同样的,如果机器宕机,会丢失最近`N`个事务的`binlog`日志。
+
+## 两阶段提交
+
+`redo log`(重做日志)让`InnoDB`存储引擎拥有了崩溃恢复能力。
+
+`binlog`(归档日志)保证了`MySQL`集群架构的数据一致性。
+
+虽然它们都属于持久化的保证,但是则重点不同。
+
+在执行更新语句过程,会记录`redo log`与`binlog`两块日志,以基本的事务为单位,`redo log`在事务执行过程中可以不断写入,而`binlog`只有在提交事务时才写入,所以`redo log`与`binlog`的写入时机不一样。
+
+
+
+回到正题,`redo log`与`binlog`两份日志之间的逻辑不一致,会出现什么问题?
+
+我们以`update`语句为例,假设`id=2`的记录,字段`c`值是`0`,把字段`c`值更新成`1`,`SQL`语句为`update T set c=1 where id=2`。
+
+假设执行过程中写完`redo log`日志后,`binlog`日志写期间发生了异常,会出现什么情况呢?
+
+
+
+由于`binlog`没写完就异常,这时候`binlog`里面没有对应的修改记录。因此,之后用`binlog`日志恢复数据时,就会少这一次更新,恢复出来的这一行`c`值是`0`,而原库因为`redo log`日志恢复,这一行`c`值是`1`,最终数据不一致。
+
+
+
+为了解决两份日志之间的逻辑一致问题,`InnoDB`存储引擎使用**两阶段提交**方案。
+
+原理很简单,将`redo log`的写入拆成了两个步骤`prepare`和`commit`,这就是**两阶段提交**。
+
+
+
+使用**两阶段提交**后,写入`binlog`时发生异常也不会有影响,因为`MySQL`根据`redo log`日志恢复数据时,发现`redo log`还处于`prepare`阶段,并且没有对应`binlog`日志,就会回滚该事务。
+
+
+
+再看一个场景,`redo log`设置`commit`阶段发生异常,那会不会回滚事务呢?
+
+
+
+并不会回滚事务,它会执行上图框住的逻辑,虽然`redo log`是处于`prepare`阶段,但是能通过事务`id`找到对应的`binlog`日志,所以`MySQL`认为是完整的,就会提交事务恢复数据。
+
+## undo log
+
+> 这部分内容为 JavaGuide 的补充:
+
+我们知道如果想要保证事务的原子性,就需要在异常发生时,对已经执行的操作进行**回滚**,在 MySQL 中,恢复机制是通过 **回滚日志(undo log)** 实现的,所有事务进行的修改都会先先记录到这个回滚日志中,然后再执行相关的操作。如果执行过程中遇到异常的话,我们直接利用 **回滚日志** 中的信息将数据回滚到修改之前的样子即可!并且,回滚日志会先于数据持久化到磁盘上。这样就保证了即使遇到数据库突然宕机等情况,当用户再次启动数据库的时候,数据库还能够通过查询回滚日志来回滚将之前未完成的事务。
+
+另外,`MVCC` 的实现依赖于:**隐藏字段、Read View、undo log**。在内部实现中,`InnoDB` 通过数据行的 `DB_TRX_ID` 和 `Read View` 来判断数据的可见性,如不可见,则通过数据行的 `DB_ROLL_PTR` 找到 `undo log` 中的历史版本。每个事务读到的数据版本可能是不一样的,在同一个事务中,用户只能看到该事务创建 `Read View` 之前已经提交的修改和该事务本身做的修改
+
+## 总结
+
+> 这部分内容为 JavaGuide 的补充:
+
+MySQL InnoDB 引擎使用 **redo log(重做日志)** 保证事务的**持久性**,使用 **undo log(回滚日志)** 来保证事务的**原子性**。
+
+`MySQL`数据库的**数据备份、主备、主主、主从**都离不开`binlog`,需要依靠`binlog`来同步数据,保证数据一致性。
+
+## 站在巨人的肩膀上
+
+- 《MySQL 实战 45 讲》
+- 《从零开始带你成为 MySQL 实战优化高手》
+- 《MySQL 是怎样运行的:从根儿上理解 MySQL》
+- 《MySQL 技术 Innodb 存储引擎》
+
+## MySQL 好文推荐
+
+- [CURD 这么多年,你有了解过 MySQL 的架构设计吗?](https://mp.weixin.qq.com/s/R-1km7r0z3oWfwYQV8iiqA)
+- [浅谈 MySQL InnoDB 的内存组件](https://mp.weixin.qq.com/s/7Kab4IQsNcU_bZdbv_MuOg)
\ No newline at end of file
diff --git "a/docs/java/basis/\344\273\243\347\220\206\346\250\241\345\274\217\350\257\246\350\247\243.md" "b/docs/java/basis/\344\273\243\347\220\206\346\250\241\345\274\217\350\257\246\350\247\243.md"
index 8323cedc168..704de492bef 100644
--- "a/docs/java/basis/\344\273\243\347\220\206\346\250\241\345\274\217\350\257\246\350\247\243.md"
+++ "b/docs/java/basis/\344\273\243\347\220\206\346\250\241\345\274\217\350\257\246\350\247\243.md"
@@ -348,7 +348,7 @@ public class DebugMethodInterceptor implements MethodInterceptor {
/**
- * @param o 被代理的对象(需要增强的对象)
+ * @param o 代理对象(增强的对象)
* @param method 被拦截的方法(需要增强的方法)
* @param args 方法入参
* @param methodProxy 用于调用原始方法
diff --git "a/docs/java/collection/Java\351\233\206\345\220\210\346\241\206\346\236\266\345\270\270\350\247\201\351\235\242\350\257\225\351\242\230.md" "b/docs/java/collection/Java\351\233\206\345\220\210\346\241\206\346\236\266\345\270\270\350\247\201\351\235\242\350\257\225\351\242\230.md"
index 5c0c5b389d7..ce99f80418e 100644
--- "a/docs/java/collection/Java\351\233\206\345\220\210\346\241\206\346\236\266\345\270\270\350\247\201\351\235\242\350\257\225\351\242\230.md"
+++ "b/docs/java/collection/Java\351\233\206\345\220\210\346\241\206\346\236\266\345\270\270\350\247\201\351\235\242\350\257\225\351\242\230.md"
@@ -3,11 +3,12 @@
- [1. 剖析面试最常见问题之 Java 集合框架](#1-剖析面试最常见问题之-java-集合框架)
- [1.1. 集合概述](#11-集合概述)
- [1.1.1. Java 集合概览](#111-java-集合概览)
- - [1.1.2. 说说 List,Set,Map 三者的区别?](#112-说说-listsetmap-三者的区别)
+ - [1.1.2. 说说 List, Set, Queue, Map 四者的区别?](#112-说说-list-set-queue-map-四者的区别)
- [1.1.3. 集合框架底层数据结构总结](#113-集合框架底层数据结构总结)
- [1.1.3.1. List](#1131-list)
- [1.1.3.2. Set](#1132-set)
- - [1.1.3.3. Map](#1133-map)
+ - [1.1.3.3 Queue](#1133-queue)
+ - [1.1.3.4. Map](#1134-map)
- [1.1.4. 如何选用集合?](#114-如何选用集合)
- [1.1.5. 为什么要使用集合?](#115-为什么要使用集合)
- [1.2. Collection 子接口之 List](#12-collection-子接口之-list)
@@ -22,25 +23,29 @@
- [1.3.1.2. 重写 compareTo 方法实现按年龄来排序](#1312-重写-compareto-方法实现按年龄来排序)
- [1.3.2. 无序性和不可重复性的含义是什么](#132-无序性和不可重复性的含义是什么)
- [1.3.3. 比较 HashSet、LinkedHashSet 和 TreeSet 三者的异同](#133-比较-hashsetlinkedhashset-和-treeset-三者的异同)
- - [1.4. Map 接口](#14-map-接口)
- - [1.4.1. HashMap 和 Hashtable 的区别](#141-hashmap-和-hashtable-的区别)
- - [1.4.2. HashMap 和 HashSet 区别](#142-hashmap-和-hashset-区别)
- - [1.4.3. HashMap 和 TreeMap 区别](#143-hashmap-和-treemap-区别)
- - [1.4.4. HashSet 如何检查重复](#144-hashset-如何检查重复)
- - [1.4.5. HashMap 的底层实现](#145-hashmap-的底层实现)
- - [1.4.5.1. JDK1.8 之前](#1451-jdk18-之前)
- - [1.4.5.2. JDK1.8 之后](#1452-jdk18-之后)
- - [1.4.6. HashMap 的长度为什么是 2 的幂次方](#146-hashmap-的长度为什么是-2-的幂次方)
- - [1.4.7. HashMap 多线程操作导致死循环问题](#147-hashmap-多线程操作导致死循环问题)
- - [1.4.8. HashMap 有哪几种常见的遍历方式?](#148-hashmap-有哪几种常见的遍历方式)
- - [1.4.9. ConcurrentHashMap 和 Hashtable 的区别](#149-concurrenthashmap-和-hashtable-的区别)
- - [1.4.10. ConcurrentHashMap 线程安全的具体实现方式/底层具体实现](#1410-concurrenthashmap-线程安全的具体实现方式底层具体实现)
- - [1.4.10.1. JDK1.7(上面有示意图)](#14101-jdk17上面有示意图)
- - [1.4.10.2. JDK1.8 (上面有示意图)](#14102-jdk18-上面有示意图)
- - [1.5. Collections 工具类](#15-collections-工具类)
- - [1.5.1. 排序操作](#151-排序操作)
- - [1.5.2. 查找,替换操作](#152-查找替换操作)
- - [1.5.3. 同步控制](#153-同步控制)
+ - [1.4 Collection 子接口之 Queue](#14-collection-子接口之-queue)
+ - [1.4.1 Queue 与 Deque 的区别](#141-queue-与-deque-的区别)
+ - [1.4.2 ArrayDeque 与 LinkedList 的区别](#142-arraydeque-与-linkedlist-的区别)
+ - [1.4.3 说一说 PriorityQueue](#143-说一说-priorityqueue)
+ - [1.5. Map 接口](#15-map-接口)
+ - [1.5.1. HashMap 和 Hashtable 的区别](#151-hashmap-和-hashtable-的区别)
+ - [1.5.2. HashMap 和 HashSet 区别](#152-hashmap-和-hashset-区别)
+ - [1.5.3. HashMap 和 TreeMap 区别](#153-hashmap-和-treemap-区别)
+ - [1.5.4. HashSet 如何检查重复](#154-hashset-如何检查重复)
+ - [1.5.5. HashMap 的底层实现](#155-hashmap-的底层实现)
+ - [1.5.5.1. JDK1.8 之前](#1551-jdk18-之前)
+ - [1.5.5.2. JDK1.8 之后](#1552-jdk18-之后)
+ - [1.5.6. HashMap 的长度为什么是 2 的幂次方](#156-hashmap-的长度为什么是-2-的幂次方)
+ - [1.5.7. HashMap 多线程操作导致死循环问题](#157-hashmap-多线程操作导致死循环问题)
+ - [1.5.8. HashMap 有哪几种常见的遍历方式?](#158-hashmap-有哪几种常见的遍历方式)
+ - [1.5.9. ConcurrentHashMap 和 Hashtable 的区别](#159-concurrenthashmap-和-hashtable-的区别)
+ - [1.5.10. ConcurrentHashMap 线程安全的具体实现方式/底层具体实现](#1510-concurrenthashmap-线程安全的具体实现方式底层具体实现)
+ - [1.5.10.1. JDK1.7(上面有示意图)](#15101-jdk17上面有示意图)
+ - [1.5.10.2. JDK1.8 (上面有示意图)](#15102-jdk18-上面有示意图)
+ - [1.6. Collections 工具类](#16-collections-工具类)
+ - [1.6.1. 排序操作](#161-排序操作)
+ - [1.6.2. 查找,替换操作](#162-查找替换操作)
+ - [1.6.3. 同步控制](#163-同步控制)
@@ -50,19 +55,21 @@
### 1.1.1. Java 集合概览
-从下图可以看出,在 Java 中除了以 `Map` 结尾的类之外, 其他类都实现了 `Collection` 接口。
+Java 集合, 也叫作容器,主要是由两大接口派生而来:一个是 `Collecton`接口,主要用于存放单一元素;另一个是 `Map` 接口,主要用于存放键值对。对于`Collection` 接口,下面又有三个主要的子接口:`List`、`Set` 和 `Queue`。
-并且,以 `Map` 结尾的类都实现了 `Map` 接口。
+Java 集合框架如下图所示:
-
+
-https://www.javatpoint.com/collections-in-java
-### 1.1.2. 说说 List,Set,Map 三者的区别?
+注:图中只列举了主要的继承派生关系,并没有列举所有关系。比方省略了`AbstractList`, `NavigableSet`等抽象类以及其他的一些辅助类,如想深入了解,可自行查看源码。
-- `List`(对付顺序的好帮手): 存储的元素是有序的、可重复的。
+### 1.1.2. 说说 List, Set, Queue, Map 四者的区别?
+
+- `List`(对付顺序的好帮手): 存储的元素是有序的、可重复的。
- `Set`(注重独一无二的性质): 存储的元素是无序的、不可重复的。
-- `Map`(用 Key 来搜索的专家): 使用键值对(key-value)存储,类似于数学上的函数 y=f(x),“x”代表 key,"y"代表 value,Key 是无序的、不可重复的,value 是无序的、可重复的,每个键最多映射到一个值。
+- `Queue`(实现排队功能的叫号机): 按特定的排队规则来确定先后顺序,存储的元素是有序的、可重复的。
+- `Map`(用 key 来搜索的专家): 使用键值对(key-value)存储,类似于数学上的函数 y=f(x),"x" 代表 key,"y" 代表 value,key 是无序的、不可重复的,value 是无序的、可重复的,每个键最多映射到一个值。
### 1.1.3. 集合框架底层数据结构总结
@@ -70,19 +77,23 @@
#### 1.1.3.1. List
-- `Arraylist`: `Object[]`数组
-- `Vector`:`Object[]`数组
+- `Arraylist`: `Object[]` 数组
+- `Vector`:`Object[]` 数组
- `LinkedList`: 双向链表(JDK1.6 之前为循环链表,JDK1.7 取消了循环)
#### 1.1.3.2. Set
-- `HashSet`(无序,唯一): 基于 `HashMap` 实现的,底层采用 `HashMap` 来保存元素
-- `LinkedHashSet`:`LinkedHashSet` 是 `HashSet` 的子类,并且其内部是通过 `LinkedHashMap` 来实现的。有点类似于我们之前说的 `LinkedHashMap` 其内部是基于 `HashMap` 实现一样,不过还是有一点点区别的
-- `TreeSet`(有序,唯一): 红黑树(自平衡的排序二叉树)
+- `HashSet`(无序,唯一): 基于 `HashMap` 实现的,底层采用 `HashMap` 来保存元素
+- `LinkedHashSet`: `LinkedHashSet` 是 `HashSet` 的子类,并且其内部是通过 `LinkedHashMap` 来实现的。有点类似于我们之前说的 `LinkedHashMap` 其内部是基于 `HashMap` 实现一样,不过还是有一点点区别的
+- `TreeSet`(有序,唯一): 红黑树(自平衡的排序二叉树)
+
+#### 1.1.3.3 Queue
+- `PriorityQueue`: `Object[]` 数组来实现二叉堆
+- `ArrayQueue`: `Object[]` 数组 + 双指针
再来看看 `Map` 接口下面的集合。
-#### 1.1.3.3. Map
+#### 1.1.3.4. Map
- `HashMap`: JDK1.8 之前 `HashMap` 由数组+链表组成的,数组是 `HashMap` 的主体,链表则是主要为了解决哈希冲突而存在的(“拉链法”解决冲突)。JDK1.8 以后在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为 8)(将链表转换成红黑树前会判断,如果当前数组的长度小于 64,那么会选择先进行数组扩容,而不是转换为红黑树)时,将链表转化为红黑树,以减少搜索时间
- `LinkedHashMap`: `LinkedHashMap` 继承自 `HashMap`,所以它的底层仍然是基于拉链式散列结构即由数组和链表或红黑树组成。另外,`LinkedHashMap` 在上面结构的基础上,增加了一条双向链表,使得上面的结构可以保持键值对的插入顺序。同时通过对链表进行相应的操作,实现了访问顺序相关逻辑。详细可以查看:[《LinkedHashMap 源码详细分析(JDK1.8)》](https://www.imooc.com/article/22931)
@@ -304,9 +315,66 @@ Output:
`TreeSet` 底层使用红黑树,能够按照添加元素的顺序进行遍历,排序的方式有自然排序和定制排序。
-## 1.4. Map 接口
+## 1.4 Collection 子接口之 Queue
+
+### 1.4.1 Queue 与 Deque 的区别
+
+`Queue` 是单端队列,只能从一端插入元素,另一端删除元素,实现上一般遵循 **先进先出(FIFO)** 规则。
+
+`Queue` 扩展了 `Collection` 的接口,根据 **因为容量问题而导致操作失败后处理方式的不同** 可以分为两类方法: 一种在操作失败后会抛出异常,另一种则会返回特殊值。
+
+| `Queue` 接口| 抛出异常 | 返回特殊值 |
+| ------------ | --------- | ---------- |
+| 插入队尾 | add(E e) | offer(E e) |
+| 删除队首 | remove() | poll() |
+| 查询队首元素 | element() | peek() |
+
+`Deque` 是双端队列,在队列的两端均可以插入或删除元素。
+
+`Deque` 扩展了 `Queue` 的接口, 增加了在队首和队尾进行插入和删除的方法,同样根据失败后处理方式的不同分为两类:
+
+| `Deque` 接口 | 抛出异常 | 返回特殊值 |
+| ------------ | ------------- | --------------- |
+| 插入队首 | addFirst(E e) | offerFirst(E e) |
+| 插入队尾 | addLast(E e) | offerLast(E e) |
+| 删除队首 | removeFirst() | pollFirst() |
+| 删除队尾 | removeLast() | pollLast() |
+| 查询队首元素 | getFirst() | peekFirst() |
+| 查询队尾元素 | getLast() | peekLast() |
+
+事实上,`Deque` 还提供有 `push()` 和 `pop()` 等其他方法,可用于模拟栈。
+
+
+### 1.4.2 ArrayDeque 与 LinkedList 的区别
+
+`ArrayDeque` 和 `LinkedList` 都实现了 `Deque` 接口,两者都具有队列的功能,但两者有什么区别呢?
+
+- `ArrayDeque` 是基于可变长的数组和双指针来实现,而 `LinkedList` 则通过链表来实现。
+
+- `ArrayDeque` 不支持存储 `NULL` 数据,但 `LinkedList` 支持。
+
+- `ArrayDeque` 是在 JDK1.6 才被引入的,而`LinkedList` 早在 JDK1.2 时就已经存在。
+
+- `ArrayDeque` 插入时可能存在扩容过程, 不过均摊后的插入操作依然为 O(1)。虽然 `LinkedList` 不需要扩容,但是每次插入数据时均需要申请新的堆空间,均摊性能相比更慢。
+
+从性能的角度上,选用 `ArrayDeque` 来实现队列要比 `LinkedList` 更好。此外,`ArrayDeque` 也可以用于实现栈。
+
+### 1.4.3 说一说 PriorityQueue
+
+`PriorityQueue` 是在 JDK1.5 中被引入的, 其与 `Queue` 的区别在于元素出队顺序是与优先级相关的,即总是优先级最高的元素先出队。
+
+这里列举其相关的一些要点:
+
+- `PriorityQueue` 利用了二叉堆的数据结构来实现的,底层使用可变长的数组来存储数据
+- `PriorityQueue` 通过堆元素的上浮和下沉,实现了在 O(logn) 的时间复杂度内插入元素和删除堆顶元素。
+- `PriorityQueue` 是非线程安全的,且不支持存储 `NULL` 和 `non-comparable` 的对象。
+- `PriorityQueue` 默认是小顶堆,但可以接收一个 `Comparator` 作为构造参数,从而来自定义元素优先级的先后。
+
+`PriorityQueue` 在面试中可能更多的会出现在手撕算法的时候,典型例题包括堆排序、求第K大的数、带权图的遍历等,所以需要会熟练使用才行。
+
+## 1.5. Map 接口
-### 1.4.1. HashMap 和 Hashtable 的区别
+### 1.5.1. HashMap 和 Hashtable 的区别
1. **线程是否安全:** `HashMap` 是非线程安全的,`HashTable` 是线程安全的,因为 `HashTable` 内部的方法基本都经过`synchronized` 修饰。(如果你要保证线程安全的话就使用 `ConcurrentHashMap` 吧!);
2. **效率:** 因为线程安全的问题,`HashMap` 要比 `HashTable` 效率高一点。另外,`HashTable` 基本被淘汰,不要在代码中使用它;
@@ -351,7 +419,7 @@ Output:
}
```
-### 1.4.2. HashMap 和 HashSet 区别
+### 1.5.2. HashMap 和 HashSet 区别
如果你看过 `HashSet` 源码的话就应该知道:`HashSet` 底层就是基于 `HashMap` 实现的。(`HashSet` 的源码非常非常少,因为除了 `clone()`、`writeObject()`、`readObject()`是 `HashSet` 自己不得不实现之外,其他方法都是直接调用 `HashMap` 中的方法。
@@ -362,7 +430,7 @@ Output:
| 调用 `put()`向 map 中添加元素 | 调用 `add()`方法向 `Set` 中添加元素 |
| `HashMap` 使用键(Key)计算 `hashcode` | `HashSet` 使用成员对象来计算 `hashcode` 值,对于两个对象来说 `hashcode` 可能相同,所以`equals()`方法用来判断对象的相等性 |
-### 1.4.3. HashMap 和 TreeMap 区别
+### 1.5.3. HashMap 和 TreeMap 区别
`TreeMap` 和`HashMap` 都继承自`AbstractMap` ,但是需要注意的是`TreeMap`它还实现了`NavigableMap`接口和`SortedMap` 接口。
@@ -430,7 +498,7 @@ TreeMap treeMap = new TreeMap<>((person1, person2) -> {
**综上,相比于`HashMap`来说 `TreeMap` 主要多了对集合中的元素根据键排序的能力以及对集合内元素的搜索的能力。**
-### 1.4.4. HashSet 如何检查重复
+### 1.5.4. HashSet 如何检查重复
以下内容摘自我的 Java 启蒙书《Head first java》第二版:
@@ -473,9 +541,9 @@ final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
对于引用类型(包括包装类型)来说,equals 如果没有被重写,对比它们的地址是否相等;如果 equals()方法被重写(例如 String),则比较的是地址里的内容。
-### 1.4.5. HashMap 的底层实现
+### 1.5.5. HashMap 的底层实现
-#### 1.4.5.1. JDK1.8 之前
+#### 1.5.5.1. JDK1.8 之前
JDK1.8 之前 `HashMap` 底层是 **数组和链表** 结合在一起使用也就是 **链表散列**。**HashMap 通过 key 的 hashCode 经过扰动函数处理过后得到 hash 值,然后通过 (n - 1) & hash 判断当前元素存放的位置(这里的 n 指的是数组的长度),如果当前位置存在元素的话,就判断该元素与要存入的元素的 hash 值以及 key 是否相同,如果相同的话,直接覆盖,不相同就通过拉链法解决冲突。**
@@ -514,7 +582,7 @@ static int hash(int h) {

-#### 1.4.5.2. JDK1.8 之后
+#### 1.5.5.2. JDK1.8 之后
相比于之前的版本, JDK1.8 之后在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为 8)(将链表转换成红黑树前会判断,如果当前数组的长度小于 64,那么会选择先进行数组扩容,而不是转换为红黑树)时,将链表转化为红黑树,以减少搜索时间。
@@ -522,7 +590,7 @@ static int hash(int h) {
> TreeMap、TreeSet 以及 JDK1.8 之后的 HashMap 底层都用到了红黑树。红黑树就是为了解决二叉查找树的缺陷,因为二叉查找树在某些情况下会退化成一个线性结构。
-### 1.4.6. HashMap 的长度为什么是 2 的幂次方
+### 1.5.6. HashMap 的长度为什么是 2 的幂次方
为了能让 HashMap 存取高效,尽量较少碰撞,也就是要尽量把数据分配均匀。我们上面也讲到了过了,Hash 值的范围值-2147483648 到 2147483647,前后加起来大概 40 亿的映射空间,只要哈希函数映射得比较均匀松散,一般应用是很难出现碰撞的。但问题是一个 40 亿长度的数组,内存是放不下的。所以这个散列值是不能直接拿来用的。用之前还要先做对数组的长度取模运算,得到的余数才能用来要存放的位置也就是对应的数组下标。这个数组下标的计算方法是“ `(n - 1) & hash`”。(n 代表数组长度)。这也就解释了 HashMap 的长度为什么是 2 的幂次方。
@@ -530,17 +598,17 @@ static int hash(int h) {
我们首先可能会想到采用%取余的操作来实现。但是,重点来了:**“取余(%)操作中如果除数是 2 的幂次则等价于与其除数减一的与(&)操作(也就是说 hash%length==hash&(length-1)的前提是 length 是 2 的 n 次方;)。”** 并且 **采用二进制位操作 &,相对于%能够提高运算效率,这就解释了 HashMap 的长度为什么是 2 的幂次方。**
-### 1.4.7. HashMap 多线程操作导致死循环问题
+### 1.5.7. HashMap 多线程操作导致死循环问题
主要原因在于并发下的 Rehash 会造成元素之间会形成一个循环链表。不过,jdk 1.8 后解决了这个问题,但是还是不建议在多线程下使用 HashMap,因为多线程下使用 HashMap 还是会存在其他问题比如数据丢失。并发环境下推荐使用 ConcurrentHashMap 。
详情请查看:
-### 1.4.8. HashMap 有哪几种常见的遍历方式?
+### 1.5.8. HashMap 有哪几种常见的遍历方式?
[HashMap 的 7 种遍历方式与性能分析!](https://mp.weixin.qq.com/s/zQBN3UvJDhRTKP6SzcZFKw)
-### 1.4.9. ConcurrentHashMap 和 Hashtable 的区别
+### 1.5.9. ConcurrentHashMap 和 Hashtable 的区别
`ConcurrentHashMap` 和 `Hashtable` 的区别主要体现在实现线程安全的方式上不同。
@@ -567,9 +635,9 @@ static int hash(int h) {
JDK1.8 的 `ConcurrentHashMap` 不在是 **Segment 数组 + HashEntry 数组 + 链表**,而是 **Node 数组 + 链表 / 红黑树**。不过,Node 只能用于链表的情况,红黑树的情况需要使用 **`TreeNode`**。当冲突链表达到一定长度时,链表会转换成红黑树。
-### 1.4.10. ConcurrentHashMap 线程安全的具体实现方式/底层具体实现
+### 1.5.10. ConcurrentHashMap 线程安全的具体实现方式/底层具体实现
-#### 1.4.10.1. JDK1.7(上面有示意图)
+#### 1.5.10.1. JDK1.7(上面有示意图)
首先将数据分为一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据时,其他段的数据也能被其他线程访问。
@@ -584,13 +652,13 @@ static class Segment extends ReentrantLock implements Serializable {
一个 `ConcurrentHashMap` 里包含一个 `Segment` 数组。`Segment` 的结构和 `HashMap` 类似,是一种数组和链表结构,一个 `Segment` 包含一个 `HashEntry` 数组,每个 `HashEntry` 是一个链表结构的元素,每个 `Segment` 守护着一个 `HashEntry` 数组里的元素,当对 `HashEntry` 数组的数据进行修改时,必须首先获得对应的 `Segment` 的锁。
-#### 1.4.10.2. JDK1.8 (上面有示意图)
+#### 1.5.10.2. JDK1.8 (上面有示意图)
`ConcurrentHashMap` 取消了 `Segment` 分段锁,采用 CAS 和 `synchronized` 来保证并发安全。数据结构跟 HashMap1.8 的结构类似,数组+链表/红黑二叉树。Java 8 在链表长度超过一定阈值(8)时将链表(寻址时间复杂度为 O(N))转换为红黑树(寻址时间复杂度为 O(log(N)))
`synchronized` 只锁定当前链表或红黑二叉树的首节点,这样只要 hash 不冲突,就不会产生并发,效率又提升 N 倍。
-## 1.5. Collections 工具类
+## 1.6. Collections 工具类
Collections 工具类常用方法:
@@ -598,7 +666,7 @@ Collections 工具类常用方法:
2. 查找,替换操作
3. 同步控制(不推荐,需要线程安全的集合类型时请考虑使用 JUC 包下的并发集合)
-### 1.5.1. 排序操作
+### 1.6.1. 排序操作
```java
void reverse(List list)//反转
@@ -609,7 +677,7 @@ void swap(List list, int i , int j)//交换两个索引位置的元素
void rotate(List list, int distance)//旋转。当distance为正数时,将list后distance个元素整体移到前面。当distance为负数时,将 list的前distance个元素整体移到后面
```
-### 1.5.2. 查找,替换操作
+### 1.6.2. 查找,替换操作
```java
int binarySearch(List list, Object key)//对List进行二分查找,返回索引,注意List必须是有序的
@@ -621,7 +689,7 @@ int indexOfSubList(List list, List target)//统计target在list中第一次出
boolean replaceAll(List list, Object oldVal, Object newVal)//用新元素替换旧元素
```
-### 1.5.3. 同步控制
+### 1.6.3. 同步控制
`Collections` 提供了多个`synchronizedXxx()`方法·,该方法可以将指定集合包装成线程同步的集合,从而解决多线程并发访问集合时的线程安全问题。
diff --git a/docs/java/collection/images/java-collection-hierarchy.png b/docs/java/collection/images/java-collection-hierarchy.png
new file mode 100644
index 00000000000..78daf980845
Binary files /dev/null and b/docs/java/collection/images/java-collection-hierarchy.png differ
diff --git "a/docs/java/jvm/Java\345\206\205\345\255\230\345\214\272\345\237\237.md" "b/docs/java/jvm/Java\345\206\205\345\255\230\345\214\272\345\237\237.md"
index 11210af18d8..918585a0d6e 100644
--- "a/docs/java/jvm/Java\345\206\205\345\255\230\345\214\272\345\237\237.md"
+++ "b/docs/java/jvm/Java\345\206\205\345\255\230\345\214\272\345\237\237.md"
@@ -371,7 +371,7 @@ System.out.println(str3 == str5);//true
System.out.println(str4 == str5);//false
```
-
+
尽量避免多个字符串拼接,因为这样会重新创建对象。如果需要改变字符串的话,可以使用 StringBuilder 或者 StringBuffer。
diff --git "a/docs/java/jvm/pictures/java\345\206\205\345\255\230\345\214\272\345\237\237/\345\255\227\347\254\246\344\270\262\346\213\274\346\216\245-\345\270\270\351\207\217\346\261\240.drawio" "b/docs/java/jvm/pictures/java\345\206\205\345\255\230\345\214\272\345\237\237/\345\255\227\347\254\246\344\270\262\346\213\274\346\216\245-\345\270\270\351\207\217\346\261\240.drawio"
new file mode 100644
index 00000000000..764cc0be828
--- /dev/null
+++ "b/docs/java/jvm/pictures/java\345\206\205\345\255\230\345\214\272\345\237\237/\345\255\227\347\254\246\344\270\262\346\213\274\346\216\245-\345\270\270\351\207\217\346\261\240.drawio"
@@ -0,0 +1 @@
+7Vpdb6M4FP011j61AoMNPCZpZkYrrbRStZqZRxccsOLgDDhNMr9+bTAhfKSTtqG0melL8L3mYp9zbny5DXBmq93njKyTf0REOYBWtAPOHYDQti2sPrRlX1r8AJaGOGORmVQb7tlPaoyWsW5YRPPGRCkEl2zdNIYiTWkoGzaSZWLbnLYQvPnUNYlpx3AfEt61fmWRTMwuoFfbv1AWJ9WTbRyUnhWpJpud5AmJxPbI5MyBM8uEkOXVajejXINX4VLe9+mE97CwjKbynBuW6c/Zcu/fPOZp8vjfarvJ/57cmCiPhG/MhgHEXMWbLoQKq1Yt9wYK/GMjKsdNXhA1UROgs97VTnUV689cZnYVSS2pDFa6DBqHuDATmzSiepW2cm8TJun9moTau1WiUrZErrhxx5zkubk+IFoMllSGiRmYXdFM0t1JuOwDCUq9VKyozPZqirnBN7QZ3TqeGW9rFdiWsSVHCkDGRozw4kPkmht1Yeh5BlVwOKrQVVGF0dhUOcNR5V4VVcgfmyp3OKqc66LKHpsqNBxV8Kqoct2xqcI9VH0IJCFCTSitLpSOi7pQOtZQWHonZZ+vSfpy2dcWlQANd5UJZfwPlQmHMq3izxk7FfzB6WNpfLX0jV4fBAMdOo3sO8XgBzyK2gyi0ROwqlueOoxUGLbO6a9xFMrDpN6bOmMV1YzzmeAiK8I4EaH+Iiw5FUt65MGhTx8Wg59ePr6FrQOsp2yD2LvtOcKgjYaioKfNMEdgYgEfd7hQ25dN0JtopiKlLeiNiXAWp2oYKriosk81mCwkfGIcKxZF/BTLdT5ZPUSrTDTNKTu4DFlu0HptrcqKI6bcnkSBgyVKT4dBs3QHAg/MPTCZgQkGcxdMfTAtXPrCB/MA+B7wP4E5BlNbs/q7UuqgTv6hoMuqDfvzbzBi+/oR7W/ANJrodqnGWp8VLGwS1kaL7pj8Znz6+rsGWe2qHN3tDObFYG8G5UNp1Om4tvBVCxObLKRPbamcJ0kWU/mr4rnL1xEZ6ImzKKOcSPbYXG4fPeYJ/wpW1ASVfk69l1Uhym2au2qSO4Gg0wzkBK1AJQ6dQIVaDtt+hYD6uiSDCMh7MwWhMxXkj6qgdjVlv1RBsCVF/MYK6mvevFJBFxSDe6YYgnclBv9CYjjU6G8lhm576K8zaoaMqpcq8lBM0F8Ga72+YsVoCtDds6oFTh4on5JwGRc1wlGlvij+nlMfmH89mpWBA7rHQnwiKU5WE9ati3CDqOrYe6mQqiliscjpMNSe7lb9eV/uLRmx26AYj967tfs6Vh+7WnTO/Hq331W5iC9VLqK3Lhf7mmavVVCq1vSt0okeHGlID2sRFaPnq+idH/5tcXjoMuLAGF1IHGpY/5qlnF7/JsiZ/w8=
\ No newline at end of file
diff --git "a/docs/java/jvm/pictures/java\345\206\205\345\255\230\345\214\272\345\237\237/\345\255\227\347\254\246\344\270\262\346\213\274\346\216\245-\345\270\270\351\207\217\346\261\240.png" "b/docs/java/jvm/pictures/java\345\206\205\345\255\230\345\214\272\345\237\237/\345\255\227\347\254\246\344\270\262\346\213\274\346\216\245-\345\270\270\351\207\217\346\261\240.png"
new file mode 100644
index 00000000000..4c6f20e9508
Binary files /dev/null and "b/docs/java/jvm/pictures/java\345\206\205\345\255\230\345\214\272\345\237\237/\345\255\227\347\254\246\344\270\262\346\213\274\346\216\245-\345\270\270\351\207\217\346\261\240.png" differ
diff --git "a/docs/java/jvm/pictures/java\345\206\205\345\255\230\345\214\272\345\237\237/\345\255\227\347\254\246\344\270\262\346\213\274\346\216\245-\345\270\270\351\207\217\346\261\2402.png" "b/docs/java/jvm/pictures/java\345\206\205\345\255\230\345\214\272\345\237\237/\345\255\227\347\254\246\344\270\262\346\213\274\346\216\245-\345\270\270\351\207\217\346\261\2402.png"
deleted file mode 100644
index b680fb60204..00000000000
Binary files "a/docs/java/jvm/pictures/java\345\206\205\345\255\230\345\214\272\345\237\237/\345\255\227\347\254\246\344\270\262\346\213\274\346\216\245-\345\270\270\351\207\217\346\261\2402.png" and /dev/null differ
diff --git "a/docs/java/multi-thread/2020\346\234\200\346\226\260Java\345\271\266\345\217\221\350\277\233\351\230\266\345\270\270\350\247\201\351\235\242\350\257\225\351\242\230\346\200\273\347\273\223.md" "b/docs/java/multi-thread/2020\346\234\200\346\226\260Java\345\271\266\345\217\221\350\277\233\351\230\266\345\270\270\350\247\201\351\235\242\350\257\225\351\242\230\346\200\273\347\273\223.md"
index 8b92632dc57..365d5aec088 100644
--- "a/docs/java/multi-thread/2020\346\234\200\346\226\260Java\345\271\266\345\217\221\350\277\233\351\230\266\345\270\270\350\247\201\351\235\242\350\257\225\351\242\230\346\200\273\347\273\223.md"
+++ "b/docs/java/multi-thread/2020\346\234\200\346\226\260Java\345\271\266\345\217\221\350\277\233\351\230\266\345\270\270\350\247\201\351\235\242\350\257\225\351\242\230\346\200\273\347\273\223.md"
@@ -619,8 +619,7 @@ public ThreadPoolExecutor(int corePoolSize,
如果当前同时运行的线程数量达到最大线程数量并且队列也已经被放满了任时,`ThreadPoolTaskExecutor` 定义一些策略:
- **`ThreadPoolExecutor.AbortPolicy`:** 抛出 `RejectedExecutionException`来拒绝新任务的处理。
-- **`ThreadPoolExecutor.CallerRunsPolicy`:**
-调用执行自己的线程运行任务,也就是直接在调用`execute`方法的线程中运行(`run`)被拒绝的任务,如果执行程序已关闭,则会丢弃该任务。因此这种策略会降低对于新任务提交速度,影响程序的整体性能。如果您的应用程序可以承受此延迟并且你要求任何一个任务请求都要被执行的话,你可以选择这个策略。
+- **`ThreadPoolExecutor.CallerRunsPolicy`:** 调用执行自己的线程运行任务,也就是直接在调用`execute`方法的线程中运行(`run`)被拒绝的任务,如果执行程序已关闭,则会丢弃该任务。因此这种策略会降低对于新任务提交速度,影响程序的整体性能。如果您的应用程序可以承受此延迟并且你要求任何一个任务请求都要被执行的话,你可以选择这个策略。
- **`ThreadPoolExecutor.DiscardPolicy`:** 不处理新任务,直接丢弃掉。
- **`ThreadPoolExecutor.DiscardOldestPolicy`:** 此策略将丢弃最早的未处理的任务请求。
diff --git "a/docs/java/multi-thread/java\347\272\277\347\250\213\346\261\240\345\255\246\344\271\240\346\200\273\347\273\223.md" "b/docs/java/multi-thread/java\347\272\277\347\250\213\346\261\240\345\255\246\344\271\240\346\200\273\347\273\223.md"
index eb266f3aac2..1adf4081fef 100644
--- "a/docs/java/multi-thread/java\347\272\277\347\250\213\346\261\240\345\255\246\344\271\240\346\200\273\347\273\223.md"
+++ "b/docs/java/multi-thread/java\347\272\277\347\250\213\346\261\240\345\255\246\344\271\240\346\200\273\347\273\223.md"
@@ -173,10 +173,10 @@ public class ScheduledThreadPoolExecutor
如果当前同时运行的线程数量达到最大线程数量并且队列也已经被放满了任务时,`ThreadPoolTaskExecutor` 定义一些策略:
-- **`ThreadPoolExecutor.AbortPolicy`**:抛出 `RejectedExecutionException`来拒绝新任务的处理。
-- **`ThreadPoolExecutor.CallerRunsPolicy`**:调用执行自己的线程运行任务,也就是直接在调用`execute`方法的线程中运行(`run`)被拒绝的任务,如果执行程序已关闭,则会丢弃该任务。因此这种策略会降低对于新任务提交速度,影响程序的整体性能。如果您的应用程序可以承受此延迟并且你要求任何一个任务请求都要被执行的话,你可以选择这个策略。
-- **`ThreadPoolExecutor.DiscardPolicy`:** 不处理新任务,直接丢弃掉。
-- **`ThreadPoolExecutor.DiscardOldestPolicy`:** 此策略将丢弃最早的未处理的任务请求。
+- **`ThreadPoolExecutor.AbortPolicy`** :抛出 `RejectedExecutionException`来拒绝新任务的处理。
+- **`ThreadPoolExecutor.CallerRunsPolicy`** :调用执行自己的线程运行任务,也就是直接在调用`execute`方法的线程中运行(`run`)被拒绝的任务,如果执行程序已关闭,则会丢弃该任务。因此这种策略会降低对于新任务提交速度,影响程序的整体性能。如果您的应用程序可以承受此延迟并且你要求任何一个任务请求都要被执行的话,你可以选择这个策略。
+- **`ThreadPoolExecutor.DiscardPolicy`** :不处理新任务,直接丢弃掉。
+- **`ThreadPoolExecutor.DiscardOldestPolicy`** : 此策略将丢弃最早的未处理的任务请求。
举个例子:
diff --git "a/docs/java/multi-thread/\344\270\207\345\255\227\350\257\246\350\247\243ThreadLocal\345\205\263\351\224\256\345\255\227.md" "b/docs/java/multi-thread/\344\270\207\345\255\227\350\257\246\350\247\243ThreadLocal\345\205\263\351\224\256\345\255\227.md"
index 3650ddbb25e..a7c79807775 100644
--- "a/docs/java/multi-thread/\344\270\207\345\255\227\350\257\246\350\247\243ThreadLocal\345\205\263\351\224\256\345\255\227.md"
+++ "b/docs/java/multi-thread/\344\270\207\345\255\227\350\257\246\350\247\243ThreadLocal\345\205\263\351\224\256\345\255\227.md"
@@ -1,19 +1,19 @@
-> 本文来自一枝花算不算浪漫投稿, 原文地址:[https://juejin.im/post/5eacc1c75188256d976df748](https://juejin.im/post/5eacc1c75188256d976df748)。
+> 本文来自一枝花算不算浪漫投稿, 原文地址:[https://juejin.im/post/5eacc1c75188256d976df748](https://juejin.im/post/5eacc1c75188256d976df748)。
### 前言

-**全文共10000+字,31张图,这篇文章同样耗费了不少的时间和精力才创作完成,原创不易,请大家点点关注+在看,感谢。**
+**全文共 10000+字,31 张图,这篇文章同样耗费了不少的时间和精力才创作完成,原创不易,请大家点点关注+在看,感谢。**
对于`ThreadLocal`,大家的第一反应可能是很简单呀,线程的变量副本,每个线程隔离。那这里有几个问题大家可以思考一下:
-- `ThreadLocal`的key是**弱引用**,那么在 `ThreadLocal`.get()的时候,发生**GC**之后,key是否为**null**?
+- `ThreadLocal`的 key 是**弱引用**,那么在 `ThreadLocal`.get()的时候,发生**GC**之后,key 是否为**null**?
- `ThreadLocal`中`ThreadLocalMap`的**数据结构**?
-- `ThreadLocalMap`的**Hash算法**?
-- `ThreadLocalMap`中**Hash冲突**如何解决?
+- `ThreadLocalMap`的**Hash 算法**?
+- `ThreadLocalMap`中**Hash 冲突**如何解决?
- `ThreadLocalMap`的**扩容机制**?
-- `ThreadLocalMap`中**过期key的清理机制**?**探测式清理**和**启发式清理**流程?
+- `ThreadLocalMap`中**过期 key 的清理机制**?**探测式清理**和**启发式清理**流程?
- `ThreadLocalMap.set()`方法实现原理?
- `ThreadLocalMap.get()`方法实现原理?
- 项目中`ThreadLocal`使用情况?遇到的坑?
@@ -23,8 +23,6 @@
### 目录
-
-
**注明:** 本文源码基于`JDK 1.8`
### `ThreadLocal`代码演示
@@ -80,19 +78,18 @@ size: 0
我们还要注意`Entry`, 它的`key`是`ThreadLocal> k` ,继承自`WeakReference`, 也就是我们常说的弱引用类型。
-### GC 之后key是否为null?
+### GC 之后 key 是否为 null?
回应开头的那个问题, `ThreadLocal` 的`key`是弱引用,那么在`ThreadLocal.get()`的时候,发生`GC`之后,`key`是否是`null`?
为了搞清楚这个问题,我们需要搞清楚`Java`的**四种引用类型**:
-- **强引用**:我们常常new出来的对象就是强引用类型,只要强引用存在,垃圾回收器将永远不会回收被引用的对象,哪怕内存不足的时候
-- **软引用**:使用SoftReference修饰的对象被称为软引用,软引用指向的对象在内存要溢出的时候被回收
-- **弱引用**:使用WeakReference修饰的对象被称为弱引用,只要发生垃圾回收,若这个对象只被弱引用指向,那么就会被回收
+- **强引用**:我们常常 new 出来的对象就是强引用类型,只要强引用存在,垃圾回收器将永远不会回收被引用的对象,哪怕内存不足的时候
+- **软引用**:使用 SoftReference 修饰的对象被称为软引用,软引用指向的对象在内存要溢出的时候被回收
+- **弱引用**:使用 WeakReference 修饰的对象被称为弱引用,只要发生垃圾回收,若这个对象只被弱引用指向,那么就会被回收
- **虚引用**:虚引用是最弱的引用,在 Java 中使用 PhantomReference 进行定义。虚引用中唯一的作用就是用队列接收对象即将死亡的通知
-
-接着再来看下代码,我们使用反射的方式来看看`GC`后`ThreadLocal`中的数据情况:(下面代码来源自:https://blog.csdn.net/thewindkee/article/details/103726942 本地运行演示GC回收场景)
+接着再来看下代码,我们使用反射的方式来看看`GC`后`ThreadLocal`中的数据情况:(下面代码来源自:https://blog.csdn.net/thewindkee/article/details/103726942 本地运行演示 GC 回收场景)
```java
public class ThreadLocalDemo {
@@ -140,6 +137,7 @@ public class ThreadLocalDemo {
```
结果如下:
+
```java
弱引用key:java.lang.ThreadLocal@433619b6,值:abc
弱引用key:java.lang.ThreadLocal@418a15e3,值:java.lang.ref.SoftReference@bf97a12
@@ -192,7 +190,7 @@ void createMap(Thread t, T firstValue) {
主要的核心逻辑还是在`ThreadLocalMap`中的,一步步往下看,后面还有更详细的剖析。
-### `ThreadLocalMap` Hash算法
+### `ThreadLocalMap` Hash 算法
既然是`Map`结构,那么`ThreadLocalMap`当然也要实现自己的`hash`算法来解决散列表数组冲突问题。
@@ -200,7 +198,7 @@ void createMap(Thread t, T firstValue) {
int i = key.threadLocalHashCode & (len-1);
```
-`ThreadLocalMap`中`hash`算法很简单,这里`i`就是当前key在散列表中对应的数组下标位置。
+`ThreadLocalMap`中`hash`算法很简单,这里`i`就是当前 key 在散列表中对应的数组下标位置。
这里最关键的就是`threadLocalHashCode`值的计算,`ThreadLocal`中有一个属性为`HASH_INCREMENT = 0x61c88647`
@@ -215,7 +213,7 @@ public class ThreadLocal {
private static int nextHashCode() {
return nextHashCode.getAndAdd(HASH_INCREMENT);
}
-
+
static class ThreadLocalMap {
ThreadLocalMap(ThreadLocal> firstKey, Object firstValue) {
table = new Entry[INITIAL_CAPACITY];
@@ -231,7 +229,7 @@ public class ThreadLocal {
每当创建一个`ThreadLocal`对象,这个`ThreadLocal.nextHashCode` 这个值就会增长 `0x61c88647` 。
-这个值很特殊,它是**斐波那契数** 也叫 **黄金分割数**。`hash`增量为 这个数字,带来的好处就是 `hash` **分布非常均匀**。
+这个值很特殊,它是**斐波那契数** 也叫 **黄金分割数**。`hash`增量为 这个数字,带来的好处就是 `hash` **分布非常均匀**。
我们自己可以尝试下:
@@ -239,7 +237,7 @@ public class ThreadLocal {
可以看到产生的哈希码分布很均匀,这里不去细纠**斐波那契**具体算法,感兴趣的可以自行查阅相关资料。
-### `ThreadLocalMap` Hash冲突
+### `ThreadLocalMap` Hash 冲突
> **注明:** 下面所有示例图中,**绿色块**`Entry`代表**正常数据**,**灰色块**代表`Entry`的`key`值为`null`,**已被垃圾回收**。**白色块**表示`Entry`为`null`。
@@ -247,22 +245,21 @@ public class ThreadLocal {
`HashMap`中解决冲突的方法是在数组上构造一个**链表**结构,冲突的数据挂载到链表上,如果链表长度超过一定数量则会转化成**红黑树**。
-而`ThreadLocalMap`中并没有链表结构,所以这里不能适用`HashMap`解决冲突的方式了。
+而 `ThreadLocalMap` 中并没有链表结构,所以这里不能使用 `HashMap` 解决冲突的方式了。

+如上图所示,如果我们插入一个`value=27`的数据,通过 `hash` 计算后应该落入第 4 个槽位中,而槽位 4 已经有了 `Entry` 数据。
-如上图所示,如果我们插入一个`value=27`的数据,通过`hash`计算后应该落入第4个槽位中,而槽位4已经有了`Entry`数据。
-
-此时就会线性向后查找,一直找到`Entry`为`null`的槽位才会停止查找,将当前元素放入此槽位中。当然迭代过程中还有其他的情况,比如遇到了`Entry`不为`null`且`key`值相等的情况,还有`Entry`中的`key`值为`null`的情况等等都会有不同的处理,后面会一一详细讲解。
+此时就会线性向后查找,一直找到 `Entry` 为 `null` 的槽位才会停止查找,将当前元素放入此槽位中。当然迭代过程中还有其他的情况,比如遇到了 `Entry` 不为 `null` 且 `key` 值相等的情况,还有 `Entry` 中的 `key` 值为 `null` 的情况等等都会有不同的处理,后面会一一详细讲解。
-这里还画了一个`Entry`中的`key`为`null`的数据(**Entry=2的灰色块数据**),因为`key`值是**弱引用**类型,所以会有这种数据存在。在`set`过程中,如果遇到了`key`过期的`Entry`数据,实际上是会进行一轮**探测式清理**操作的,具体操作方式后面会讲到。
+这里还画了一个`Entry`中的`key`为`null`的数据(**Entry=2 的灰色块数据**),因为`key`值是**弱引用**类型,所以会有这种数据存在。在`set`过程中,如果遇到了`key`过期的`Entry`数据,实际上是会进行一轮**探测式清理**操作的,具体操作方式后面会讲到。
### `ThreadLocalMap.set()`详解
#### `ThreadLocalMap.set()`原理图解
-看完了`ThreadLocal` **hash算法**后,我们再来看`set`是如何实现的。
+看完了`ThreadLocal` **hash 算法**后,我们再来看`set`是如何实现的。
往`ThreadLocalMap`中`set`数据(**新增**或者**更新**数据)分为好几种情况,针对不同的情况我们画图来说说明。
@@ -282,36 +279,33 @@ public class ThreadLocal {

-遍历散列数组,线性往后查找,如果找到`Entry`为`null`的槽位,则将数据放入该槽位中,或者往后遍历过程中,遇到了**key值相等**的数据,直接更新即可。
+遍历散列数组,线性往后查找,如果找到`Entry`为`null`的槽位,则将数据放入该槽位中,或者往后遍历过程中,遇到了**key 值相等**的数据,直接更新即可。
**第四种情况:** 槽位数据不为空,往后遍历过程中,在找到`Entry`为`null`的槽位之前,遇到`key`过期的`Entry`,如下图,往后遍历过程中,一到了`index=7`的槽位数据`Entry`的`key=null`:

-散列数组下标为7位置对应的`Entry`数据`key`为`null`,表明此数据`key`值已经被垃圾回收掉了,此时就会执行`replaceStaleEntry()`方法,该方法含义是**替换过期数据的逻辑**,以**index=7**位起点开始遍历,进行探测式数据清理工作。
+散列数组下标为 7 位置对应的`Entry`数据`key`为`null`,表明此数据`key`值已经被垃圾回收掉了,此时就会执行`replaceStaleEntry()`方法,该方法含义是**替换过期数据的逻辑**,以**index=7**位起点开始遍历,进行探测式数据清理工作。
初始化探测式清理过期数据扫描的开始位置:`slotToExpunge = staleSlot = 7`
以当前`staleSlot`开始 向前迭代查找,找其他过期的数据,然后更新过期数据起始扫描下标`slotToExpunge`。`for`循环迭代,直到碰到`Entry`为`null`结束。
-如果找到了过期的数据,继续向前迭代,直到遇到`Entry=null`的槽位才停止迭代,如下图所示,**slotToExpunge被更新为0**:
+如果找到了过期的数据,继续向前迭代,直到遇到`Entry=null`的槽位才停止迭代,如下图所示,**slotToExpunge 被更新为 0**:

-以当前节点(`index=7`)向前迭代,检测是否有过期的`Entry`数据,如果有则更新`slotToExpunge`值。碰到`null`则结束探测。以上图为例`slotToExpunge`被更新为0。
+以当前节点(`index=7`)向前迭代,检测是否有过期的`Entry`数据,如果有则更新`slotToExpunge`值。碰到`null`则结束探测。以上图为例`slotToExpunge`被更新为 0。
上面向前迭代的操作是为了更新探测清理过期数据的起始下标`slotToExpunge`的值,这个值在后面会讲解,它是用来判断当前过期槽位`staleSlot`之前是否还有过期元素。
-接着开始以`staleSlot`位置(index=7)向后迭代,**如果找到了相同key值的Entry数据:**
+接着开始以`staleSlot`位置(index=7)向后迭代,**如果找到了相同 key 值的 Entry 数据:**

从当前节点`staleSlot`向后查找`key`值相等的`Entry`元素,找到后更新`Entry`的值并交换`staleSlot`元素的位置(`staleSlot`位置为过期元素),更新`Entry`数据,然后开始进行过期`Entry`的清理工作,如下图所示:
-
-
-
-**向后遍历过程中,如果没有找到相同key值的Entry数据:**
+向后遍历过程中,如果没有找到相同 key 值的 Entry 数据:

@@ -367,6 +361,7 @@ int i = key.threadLocalHashCode & (len-1);
```
什么情况下桶才是可以使用的呢?
+
1. `k = key` 说明是替换操作,可以使用
2. 碰到一个过期的桶,执行替换逻辑,占用过期桶
3. 查找过程中,碰到桶中`Entry=null`的情况,直接使用
@@ -386,16 +381,17 @@ private static int prevIndex(int i, int len) {
```
接着看剩下`for`循环中的逻辑:
+
1. 遍历当前`key`值对应的桶中`Entry`数据为空,这说明散列数组这里没有数据冲突,跳出`for`循环,直接`set`数据到对应的桶中
2. 如果`key`值对应的桶中`Entry`数据不为空
-2.1 如果`k = key`,说明当前`set`操作是一个替换操作,做替换逻辑,直接返回
-2.2 如果`key = null`,说明当前桶位置的`Entry`是过期数据,执行`replaceStaleEntry()`方法(核心方法),然后返回
+ 2.1 如果`k = key`,说明当前`set`操作是一个替换操作,做替换逻辑,直接返回
+ 2.2 如果`key = null`,说明当前桶位置的`Entry`是过期数据,执行`replaceStaleEntry()`方法(核心方法),然后返回
3. `for`循环执行完毕,继续往下执行说明向后迭代的过程中遇到了`entry`为`null`的情况
-3.1 在`Entry`为`null`的桶中创建一个新的`Entry`对象
-3.2 执行`++size`操作
+ 3.1 在`Entry`为`null`的桶中创建一个新的`Entry`对象
+ 3.2 执行`++size`操作
4. 调用`cleanSomeSlots()`做一次启发式清理工作,清理散列数组中`Entry`的`key`过期的数据
-4.1 如果清理工作完成后,未清理到任何数据,且`size`超过了阈值(数组长度的2/3),进行`rehash()`操作
-4.2 `rehash()`中会先进行一轮探测式清理,清理过期`key`,清理完成后如果**size >= threshold - threshold / 4**,就会执行真正的扩容逻辑(扩容逻辑往后看)
+ 4.1 如果清理工作完成后,未清理到任何数据,且`size`超过了阈值(数组长度的 2/3),进行`rehash()`操作
+ 4.2 `rehash()`中会先进行一轮探测式清理,清理过期`key`,清理完成后如果**size >= threshold - threshold / 4**,就会执行真正的扩容逻辑(扩容逻辑往后看)
接着重点看下`replaceStaleEntry()`方法,`replaceStaleEntry()`方法提供替换过期数据的功能,我们可以对应上面**第四种情况**的原理图来再回顾下,具体代码如下:
@@ -446,7 +442,7 @@ private void replaceStaleEntry(ThreadLocal> key, Object value,
}
```
-`slotToExpunge`表示开始探测式清理过期数据的开始下标,默认从当前的`staleSlot`开始。以当前的`staleSlot`开始,向前迭代查找,找到没有过期的数据,`for`循环一直碰到`Entry`为`null`才会结束。如果向前找到了过期数据,更新探测清理过期数据的开始下标为i,即`slotToExpunge=i`
+`slotToExpunge`表示开始探测式清理过期数据的开始下标,默认从当前的`staleSlot`开始。以当前的`staleSlot`开始,向前迭代查找,找到没有过期的数据,`for`循环一直碰到`Entry`为`null`才会结束。如果向前找到了过期数据,更新探测清理过期数据的开始下标为 i,即`slotToExpunge=i`
```java
for (int i = prevIndex(staleSlot, len);
@@ -460,7 +456,7 @@ for (int i = prevIndex(staleSlot, len);
```
接着开始从`staleSlot`向后查找,也是碰到`Entry`为`null`的桶结束。
-如果迭代过程中,**碰到k == key**,这说明这里是替换逻辑,替换新数据并且交换当前`staleSlot`位置。如果`slotToExpunge == staleSlot`,这说明`replaceStaleEntry()`一开始向前查找过期数据时并未找到过期的`Entry`数据,接着向后查找过程中也未发现过期数据,修改开始探测式清理过期数据的下标为当前循环的index,即`slotToExpunge = i`。最后调用`cleanSomeSlots(expungeStaleEntry(slotToExpunge), len);`进行启发式过期数据清理。
+如果迭代过程中,**碰到 k == key**,这说明这里是替换逻辑,替换新数据并且交换当前`staleSlot`位置。如果`slotToExpunge == staleSlot`,这说明`replaceStaleEntry()`一开始向前查找过期数据时并未找到过期的`Entry`数据,接着向后查找过程中也未发现过期数据,修改开始探测式清理过期数据的下标为当前循环的 index,即`slotToExpunge = i`。最后调用`cleanSomeSlots(expungeStaleEntry(slotToExpunge), len);`进行启发式过期数据清理。
```java
if (k == key) {
@@ -468,7 +464,7 @@ if (k == key) {
tab[i] = tab[staleSlot];
tab[staleSlot] = e;
-
+
if (slotToExpunge == staleSlot)
slotToExpunge = i;
@@ -479,7 +475,7 @@ if (k == key) {
`cleanSomeSlots()`和`expungeStaleEntry()`方法后面都会细讲,这两个是和清理相关的方法,一个是过期`key`相关`Entry`的启发式清理(`Heuristically scan`),另一个是过期`key`相关`Entry`的探测式清理。
-**如果k != key**则会接着往下走,`k == null`说明当前遍历的`Entry`是一个过期数据,`slotToExpunge == staleSlot`说明,一开始的向前查找数据并未找到过期的`Entry`。如果条件成立,则更新`slotToExpunge` 为当前位置,这个前提是前驱节点扫描时未发现过期数据。
+**如果 k != key**则会接着往下走,`k == null`说明当前遍历的`Entry`是一个过期数据,`slotToExpunge == staleSlot`说明,一开始的向前查找数据并未找到过期的`Entry`。如果条件成立,则更新`slotToExpunge` 为当前位置,这个前提是前驱节点扫描时未发现过期数据。
```java
if (k == null && slotToExpunge == staleSlot)
@@ -494,12 +490,13 @@ tab[staleSlot] = new Entry(key, value);
```
最后判断除了`staleSlot`以外,还发现了其他过期的`slot`数据,就要开启清理数据的逻辑:
+
```java
if (slotToExpunge != staleSlot)
cleanSomeSlots(expungeStaleEntry(slotToExpunge), len);
```
-### `ThreadLocalMap`过期key的探测式清理流程
+### `ThreadLocalMap`过期 key 的探测式清理流程
上面我们有提及`ThreadLocalMap`的两种过期`key`数据清理方式:**探测式清理**和**启发式清理**。
@@ -507,7 +504,7 @@ if (slotToExpunge != staleSlot)

-如上图,`set(27)` 经过hash计算后应该落到`index=4`的桶中,由于`index=4`桶已经有了数据,所以往后迭代最终数据放入到`index=7`的桶中,放入后一段时间后`index=5`中的`Entry`数据`key`变为了`null`
+如上图,`set(27)` 经过 hash 计算后应该落到`index=4`的桶中,由于`index=4`桶已经有了数据,所以往后迭代最终数据放入到`index=7`的桶中,放入后一段时间后`index=5`中的`Entry`数据`key`变为了`null`

@@ -529,7 +526,7 @@ if (slotToExpunge != staleSlot)

-执行完第二步后,index=4的元素挪到index=3的槽位中。
+执行完第二步后,index=4 的元素挪到 index=3 的槽位中。
继续往后迭代检查,碰到正常数据,计算该数据位置是否偏移,如果被偏移,则重新计算`slot`位置,目的是让正常数据尽可能存放在正确位置或离正确位置更近的位置
@@ -581,7 +578,7 @@ if (k == null) {
e.value = null;
tab[i] = null;
size--;
-}
+}
```
如果`key`没有过期,重新计算当前`key`的下标位置是不是当前槽位下标位置,如果不是,那么说明产生了`hash`冲突,此时以新计算出来正确的槽位位置往后迭代,找到最近一个可以存放`entry`的位置。
@@ -686,7 +683,7 @@ private void resize() {

-我们以`get(ThreadLocal1)`为例,通过`hash`计算后,正确的`slot`位置应该是4,而`index=4`的槽位已经有了数据,且`key`值不等于`ThreadLocal1`,所以需要继续往后迭代查找。
+我们以`get(ThreadLocal1)`为例,通过`hash`计算后,正确的`slot`位置应该是 4,而`index=4`的槽位已经有了数据,且`key`值不等于`ThreadLocal1`,所以需要继续往后迭代查找。
迭代到`index=5`的数据时,此时`Entry.key=null`,触发一次探测式数据回收操作,执行`expungeStaleEntry()`方法,执行完后,`index 5,8`的数据都会被回收,而`index 6,7`的数据都会前移,此时继续往后迭代,到`index = 6`的时候即找到了`key`值相等的`Entry`数据,如下图所示:
@@ -724,9 +721,7 @@ private Entry getEntryAfterMiss(ThreadLocal> key, int i, Entry e) {
}
```
-
-### `ThreadLocalMap`过期key的启发式清理流程
-
+### `ThreadLocalMap`过期 key 的启发式清理流程
上面多次提及到`ThreadLocalMap`过期可以的两种清理方式:**探测式清理(expungeStaleEntry())**、**启发式清理(cleanSomeSlots())**
@@ -760,7 +755,7 @@ private boolean cleanSomeSlots(int i, int n) {
我们使用`ThreadLocal`的时候,在异步场景下是无法给子线程共享父线程中创建的线程副本数据的。
-为了解决这个问题,JDK中还有一个`InheritableThreadLocal`类,我们来看一个例子:
+为了解决这个问题,JDK 中还有一个`InheritableThreadLocal`类,我们来看一个例子:
```java
public class InheritableThreadLocalDemo {
@@ -816,11 +811,11 @@ private void init(ThreadGroup g, Runnable target, String name,
我们现在项目中日志记录用的是`ELK+Logstash`,最后在`Kibana`中进行展示和检索。
-现在都是分布式系统统一对外提供服务,项目间调用的关系可以通过traceId来关联,但是不同项目之间如何传递`traceId`呢?
+现在都是分布式系统统一对外提供服务,项目间调用的关系可以通过 `traceId` 来关联,但是不同项目之间如何传递 `traceId` 呢?
-这里我们使用`org.slf4j.MDC`来实现此功能,内部就是通过`ThreadLocal`来实现的,具体实现如下:
+这里我们使用 `org.slf4j.MDC` 来实现此功能,内部就是通过 `ThreadLocal` 来实现的,具体实现如下:
-当前端发送请求到**服务A**时,**服务A**会生成一个类似`UUID`的`traceId`字符串,将此字符串放入当前线程的`ThreadLocal`中,在调用**服务B**的时候,将`traceId`写入到请求的`Header`中,**服务B**在接收请求时会先判断请求的`Header`中是否有`traceId`,如果存在则写入自己线程的`ThreadLocal`中。
+当前端发送请求到**服务 A**时,**服务 A**会生成一个类似`UUID`的`traceId`字符串,将此字符串放入当前线程的`ThreadLocal`中,在调用**服务 B**的时候,将`traceId`写入到请求的`Header`中,**服务 B**在接收请求时会先判断请求的`Header`中是否有`traceId`,如果存在则写入自己线程的`ThreadLocal`中。

@@ -830,9 +825,10 @@ private void init(ThreadGroup g, Runnable target, String name,
针对于这些场景,我们都可以有相应的解决方案,如下所示
-#### Feign远程调用解决方案
+#### Feign 远程调用解决方案
**服务发送请求:**
+
```java
@Component
@Slf4j
@@ -849,6 +845,7 @@ public class FeignInvokeInterceptor implements RequestInterceptor {
```
**服务接收请求:**
+
```java
@Slf4j
@Component
@@ -876,13 +873,13 @@ public class LogInterceptor extends HandlerInterceptorAdapter {
}
```
-#### 线程池异步调用,requestId传递
+#### 线程池异步调用,requestId 传递
因为`MDC`是基于`ThreadLocal`去实现的,异步过程中,子线程并没有办法获取到父线程`ThreadLocal`存储的数据,所以这里可以自定义线程池执行器,修改其中的`run()`方法:
```java
public class MyThreadPoolTaskExecutor extends ThreadPoolTaskExecutor {
-
+
@Override
public void execute(Runnable runnable) {
Map context = MDC.getCopyOfContextMap();
@@ -903,11 +900,6 @@ public class MyThreadPoolTaskExecutor extends ThreadPoolTaskExecutor {
}
```
-#### 使用MQ发送消息给第三方系统
-
-在MQ发送的消息体中自定义属性`requestId`,接收方消费消息后,自己解析`requestId`使用即可。
-
-
-
-
+#### 使用 MQ 发送消息给第三方系统
+在 MQ 发送的消息体中自定义属性`requestId`,接收方消费消息后,自己解析`requestId`使用即可。
diff --git "a/docs/java/multi-thread/\345\271\266\345\217\221\345\256\271\345\231\250\346\200\273\347\273\223.md" "b/docs/java/multi-thread/\345\271\266\345\217\221\345\256\271\345\231\250\346\200\273\347\273\223.md"
index fcc900e6ea6..e4042ebe76b 100644
--- "a/docs/java/multi-thread/\345\271\266\345\217\221\345\256\271\345\231\250\346\200\273\347\273\223.md"
+++ "b/docs/java/multi-thread/\345\271\266\345\217\221\345\256\271\345\231\250\346\200\273\347\273\223.md"
@@ -1,50 +1,24 @@
-点击关注[公众号](#公众号 "公众号")及时获取笔主最新更新文章,并可免费领取本文档配套的《Java 面试突击》以及 Java 工程师必备学习资源。
-
-
-
-- [一 JDK 提供的并发容器总结](#一-jdk-提供的并发容器总结 "一 JDK 提供的并发容器总结")
-- [二 ConcurrentHashMap](#二-concurrenthashmap "二 ConcurrentHashMap")
-- [三 CopyOnWriteArrayList](#三-copyonwritearraylist "三 CopyOnWriteArrayList")
- - [3.1 CopyOnWriteArrayList 简介](#31-copyonwritearraylist-简介 "3.1 CopyOnWriteArrayList 简介")
- - [3.2 CopyOnWriteArrayList 是如何做到的?](#32-copyonwritearraylist-是如何做到的? "3.2 CopyOnWriteArrayList 是如何做到的?")
- - [3.3 CopyOnWriteArrayList 读取和写入源码简单分析](#33-copyonwritearraylist-读取和写入源码简单分析 "3.3 CopyOnWriteArrayList 读取和写入源码简单分析")
- - [3.3.1 CopyOnWriteArrayList 读取操作的实现](#331-copyonwritearraylist-读取操作的实现 "3.3.1 CopyOnWriteArrayList 读取操作的实现")
- - [3.3.2 CopyOnWriteArrayList 写入操作的实现](#332-copyonwritearraylist-写入操作的实现 "3.3.2 CopyOnWriteArrayList 写入操作的实现")
-- [四 ConcurrentLinkedQueue](#四-concurrentlinkedqueue "四 ConcurrentLinkedQueue")
-- [五 BlockingQueue](#五-blockingqueue "五 BlockingQueue")
- - [5.1 BlockingQueue 简单介绍](#51-blockingqueue-简单介绍 "5.1 BlockingQueue 简单介绍")
- - [5.2 ArrayBlockingQueue](#52-arrayblockingqueue "5.2 ArrayBlockingQueue")
- - [5.3 LinkedBlockingQueue](#53-linkedblockingqueue "5.3 LinkedBlockingQueue")
- - [5.4 PriorityBlockingQueue](#54-priorityblockingqueue "5.4 PriorityBlockingQueue")
-- [六 ConcurrentSkipListMap](#六-concurrentskiplistmap "六 ConcurrentSkipListMap")
-- [七 参考](#七-参考 "七 参考")
-
-
-
-## 一 JDK 提供的并发容器总结
+## JDK 提供的并发容器总结
JDK 提供的这些容器大部分在 `java.util.concurrent` 包中。
-- **ConcurrentHashMap:** 线程安全的 HashMap
-- **CopyOnWriteArrayList:** 线程安全的 List,在读多写少的场合性能非常好,远远好于 Vector.
-- **ConcurrentLinkedQueue:** 高效的并发队列,使用链表实现。可以看做一个线程安全的 LinkedList,这是一个非阻塞队列。
-- **BlockingQueue:** 这是一个接口,JDK 内部通过链表、数组等方式实现了这个接口。表示阻塞队列,非常适合用于作为数据共享的通道。
-- **ConcurrentSkipListMap:** 跳表的实现。这是一个 Map,使用跳表的数据结构进行快速查找。
+- **`ConcurrentHashMap`** : 线程安全的 `HashMap`
+- **`CopyOnWriteArrayList`** : 线程安全的 `List`,在读多写少的场合性能非常好,远远好于 `Vector`。
+- **`ConcurrentLinkedQueue`** : 高效的并发队列,使用链表实现。可以看做一个线程安全的 `LinkedList`,这是一个非阻塞队列。
+- **`BlockingQueue`** : 这是一个接口,JDK 内部通过链表、数组等方式实现了这个接口。表示阻塞队列,非常适合用于作为数据共享的通道。
+- **`ConcurrentSkipListMap`** : 跳表的实现。这是一个 Map,使用跳表的数据结构进行快速查找。
-## 二 ConcurrentHashMap
+## ConcurrentHashMap
-我们知道 HashMap 不是线程安全的,在并发场景下如果要保证一种可行的方式是使用 `Collections.synchronizedMap()` 方法来包装我们的 HashMap。但这是通过使用一个全局的锁来同步不同线程间的并发访问,因此会带来不可忽视的性能问题。
+我们知道 `HashMap` 不是线程安全的,在并发场景下如果要保证一种可行的方式是使用 `Collections.synchronizedMap()` 方法来包装我们的 `HashMap`。但这是通过使用一个全局的锁来同步不同线程间的并发访问,因此会带来不可忽视的性能问题。
-所以就有了 HashMap 的线程安全版本—— ConcurrentHashMap 的诞生。在 ConcurrentHashMap 中,无论是读操作还是写操作都能保证很高的性能:在进行读操作时(几乎)不需要加锁,而在写操作时通过锁分段技术只对所操作的段加锁而不影响客户端对其它段的访问。
+所以就有了 `HashMap` 的线程安全版本—— `ConcurrentHashMap` 的诞生。
-关于 ConcurrentHashMap 相关问题,我在 [Java 集合框架常见面试题](https://github.com/Snailclimb/JavaGuide/blob/master/docs/java/collection/Java%E9%9B%86%E5%90%88%E6%A1%86%E6%9E%B6%E5%B8%B8%E8%A7%81%E9%9D%A2%E8%AF%95%E9%A2%98.md "Java集合框架常见面试题") 这篇文章中已经提到过。下面梳理一下关于 ConcurrentHashMap 比较重要的问题:
+在 `ConcurrentHashMap` 中,无论是读操作还是写操作都能保证很高的性能:在进行读操作时(几乎)不需要加锁,而在写操作时通过锁分段技术只对所操作的段加锁而不影响客户端对其它段的访问。
-- [ConcurrentHashMap 和 Hashtable 的区别](https://github.com/Snailclimb/JavaGuide/blob/master/docs/java/collection/Java%E9%9B%86%E5%90%88%E6%A1%86%E6%9E%B6%E5%B8%B8%E8%A7%81%E9%9D%A2%E8%AF%95%E9%A2%98.md#concurrenthashmap-%E5%92%8C-hashtable-%E7%9A%84%E5%8C%BA%E5%88%AB "ConcurrentHashMap 和 Hashtable 的区别")
-- [ConcurrentHashMap 线程安全的具体实现方式/底层具体实现](https://github.com/Snailclimb/JavaGuide/blob/master/docs/java/collection/Java%E9%9B%86%E5%90%88%E6%A1%86%E6%9E%B6%E5%B8%B8%E8%A7%81%E9%9D%A2%E8%AF%95%E9%A2%98.md#concurrenthashmap%E7%BA%BF%E7%A8%8B%E5%AE%89%E5%85%A8%E7%9A%84%E5%85%B7%E4%BD%93%E5%AE%9E%E7%8E%B0%E6%96%B9%E5%BC%8F%E5%BA%95%E5%B1%82%E5%85%B7%E4%BD%93%E5%AE%9E%E7%8E%B0 "ConcurrentHashMap线程安全的具体实现方式/底层具体实现")
+## CopyOnWriteArrayList
-## 三 CopyOnWriteArrayList
-
-### 3.1 CopyOnWriteArrayList 简介
+### CopyOnWriteArrayList 简介
```java
public class CopyOnWriteArrayList
@@ -52,21 +26,21 @@ extends Object
implements List, RandomAccess, Cloneable, Serializable
```
-在很多应用场景中,读操作可能会远远大于写操作。由于读操作根本不会修改原有的数据,因此对于每次读取都进行加锁其实是一种资源浪费。我们应该允许多个线程同时访问 List 的内部数据,毕竟读取操作是安全的。
+在很多应用场景中,读操作可能会远远大于写操作。由于读操作根本不会修改原有的数据,因此对于每次读取都进行加锁其实是一种资源浪费。我们应该允许多个线程同时访问 `List` 的内部数据,毕竟读取操作是安全的。
这和我们之前在多线程章节讲过 `ReentrantReadWriteLock` 读写锁的思想非常类似,也就是读读共享、写写互斥、读写互斥、写读互斥。JDK 中提供了 `CopyOnWriteArrayList` 类比相比于在读写锁的思想又更进一步。为了将读取的性能发挥到极致,`CopyOnWriteArrayList` 读取是完全不用加锁的,并且更厉害的是:写入也不会阻塞读取操作。只有写入和写入之间需要进行同步等待。这样一来,读操作的性能就会大幅度提升。**那它是怎么做的呢?**
-### 3.2 CopyOnWriteArrayList 是如何做到的?
+### CopyOnWriteArrayList 是如何做到的?
`CopyOnWriteArrayList` 类的所有可变操作(add,set 等等)都是通过创建底层数组的新副本来实现的。当 List 需要被修改的时候,我并不修改原有内容,而是对原有数据进行一次复制,将修改的内容写入副本。写完之后,再将修改完的副本替换原来的数据,这样就可以保证写操作不会影响读操作了。
-从 `CopyOnWriteArrayList` 的名字就能看出`CopyOnWriteArrayList` 是满足`CopyOnWrite` 的 ArrayList,所谓`CopyOnWrite` 也就是说:在计算机,如果你想要对一块内存进行修改时,我们不在原有内存块中进行写操作,而是将内存拷贝一份,在新的内存中进行写操作,写完之后呢,就将指向原来内存指针指向新的内存,原来的内存就可以被回收掉了。
+从 `CopyOnWriteArrayList` 的名字就能看出 `CopyOnWriteArrayList` 是满足 `CopyOnWrite` 的。所谓 `CopyOnWrite` 也就是说:在计算机,如果你想要对一块内存进行修改时,我们不在原有内存块中进行写操作,而是将内存拷贝一份,在新的内存中进行写操作,写完之后呢,就将指向原来内存指针指向新的内存,原来的内存就可以被回收掉了。
-### 3.3 CopyOnWriteArrayList 读取和写入源码简单分析
+### CopyOnWriteArrayList 读取和写入源码简单分析
-#### 3.3.1 CopyOnWriteArrayList 读取操作的实现
+#### CopyOnWriteArrayList 读取操作的实现
-读取操作没有任何同步控制和锁操作,理由就是内部数组 array 不会发生修改,只会被另外一个 array 替换,因此可以保证数据安全。
+读取操作没有任何同步控制和锁操作,理由就是内部数组 `array` 不会发生修改,只会被另外一个 `array` 替换,因此可以保证数据安全。
```java
/** The array, accessed only via getArray/setArray. */
@@ -86,7 +60,7 @@ implements List, RandomAccess, Cloneable, Serializable
#### 3.3.2 CopyOnWriteArrayList 写入操作的实现
-CopyOnWriteArrayList 写入操作 add() 方法在添加集合的时候加了锁,保证了同步,避免了多线程写的时候会 copy 出多个副本出来。
+`CopyOnWriteArrayList` 写入操作 `add()`方法在添加集合的时候加了锁,保证了同步,避免了多线程写的时候会 copy 出多个副本出来。
```java
/**
@@ -111,41 +85,49 @@ CopyOnWriteArrayList 写入操作 add() 方法在添加集合的时候加了锁
}
```
-## 四 ConcurrentLinkedQueue
+## ConcurrentLinkedQueue
-Java 提供的线程安全的 Queue 可以分为**阻塞队列**和**非阻塞队列**,其中阻塞队列的典型例子是 BlockingQueue,非阻塞队列的典型例子是 ConcurrentLinkedQueue,在实际应用中要根据实际需要选用阻塞队列或者非阻塞队列。 **阻塞队列可以通过加锁来实现,非阻塞队列可以通过 CAS 操作实现。**
+Java 提供的线程安全的 `Queue` 可以分为**阻塞队列**和**非阻塞队列**,其中阻塞队列的典型例子是 `BlockingQueue`,非阻塞队列的典型例子是 `ConcurrentLinkedQueue`,在实际应用中要根据实际需要选用阻塞队列或者非阻塞队列。 **阻塞队列可以通过加锁来实现,非阻塞队列可以通过 CAS 操作实现。**
-从名字可以看出,`ConcurrentLinkedQueue`这个队列使用链表作为其数据结构.ConcurrentLinkedQueue 应该算是在高并发环境中性能最好的队列了。它之所有能有很好的性能,是因为其内部复杂的实现。
+从名字可以看出,`ConcurrentLinkedQueue`这个队列使用链表作为其数据结构.`ConcurrentLinkedQueue` 应该算是在高并发环境中性能最好的队列了。它之所有能有很好的性能,是因为其内部复杂的实现。
-ConcurrentLinkedQueue 内部代码我们就不分析了,大家知道 ConcurrentLinkedQueue 主要使用 CAS 非阻塞算法来实现线程安全就好了。
+`ConcurrentLinkedQueue` 内部代码我们就不分析了,大家知道 `ConcurrentLinkedQueue` 主要使用 CAS 非阻塞算法来实现线程安全就好了。
-ConcurrentLinkedQueue 适合在对性能要求相对较高,同时对队列的读写存在多个线程同时进行的场景,即如果对队列加锁的成本较高则适合使用无锁的 ConcurrentLinkedQueue 来替代。
+`ConcurrentLinkedQueue` 适合在对性能要求相对较高,同时对队列的读写存在多个线程同时进行的场景,即如果对队列加锁的成本较高则适合使用无锁的 `ConcurrentLinkedQueue` 来替代。
-## 五 BlockingQueue
+## BlockingQueue
-### 5.1 BlockingQueue 简单介绍
+### BlockingQueue 简介
-上面我们己经提到了 ConcurrentLinkedQueue 作为高性能的非阻塞队列。下面我们要讲到的是阻塞队列——BlockingQueue。阻塞队列(BlockingQueue)被广泛使用在“生产者-消费者”问题中,其原因是 BlockingQueue 提供了可阻塞的插入和移除的方法。当队列容器已满,生产者线程会被阻塞,直到队列未满;当队列容器为空时,消费者线程会被阻塞,直至队列非空时为止。
+上面我们己经提到了 `ConcurrentLinkedQueue` 作为高性能的非阻塞队列。下面我们要讲到的是阻塞队列——`BlockingQueue`。阻塞队列(`BlockingQueue`)被广泛使用在“生产者-消费者”问题中,其原因是 `BlockingQueue` 提供了可阻塞的插入和移除的方法。当队列容器已满,生产者线程会被阻塞,直到队列未满;当队列容器为空时,消费者线程会被阻塞,直至队列非空时为止。
-BlockingQueue 是一个接口,继承自 Queue,所以其实现类也可以作为 Queue 的实现来使用,而 Queue 又继承自 Collection 接口。下面是 BlockingQueue 的相关实现类:
+`BlockingQueue` 是一个接口,继承自 `Queue`,所以其实现类也可以作为 `Queue` 的实现来使用,而 `Queue` 又继承自 `Collection` 接口。下面是 `BlockingQueue` 的相关实现类:

-**下面主要介绍一下:ArrayBlockingQueue、LinkedBlockingQueue、PriorityBlockingQueue,这三个 BlockingQueue 的实现类。**
+下面主要介绍一下 3 个常见的 `BlockingQueue` 的实现类:`ArrayBlockingQueue`、`LinkedBlockingQueue` 、`PriorityBlockingQueue` 。
+
+### ArrayBlockingQueue
+
+`ArrayBlockingQueue` 是 `BlockingQueue` 接口的有界队列实现类,底层采用数组来实现。
-### 5.2 ArrayBlockingQueue
+```java
+public class ArrayBlockingQueue
+extends AbstractQueue
+implements BlockingQueue, Serializable{}
+```
-**ArrayBlockingQueue** 是 BlockingQueue 接口的有界队列实现类,底层采用**数组**来实现。ArrayBlockingQueue 一旦创建,容量不能改变。其并发控制采用可重入锁来控制,不管是插入操作还是读取操作,都需要获取到锁才能进行操作。当队列容量满时,尝试将元素放入队列将导致操作阻塞;尝试从一个空队列中取一个元素也会同样阻塞。
+`ArrayBlockingQueue` 一旦创建,容量不能改变。其并发控制采用可重入锁 `ReentrantLock` ,不管是插入操作还是读取操作,都需要获取到锁才能进行操作。当队列容量满时,尝试将元素放入队列将导致操作阻塞;尝试从一个空队列中取一个元素也会同样阻塞。
-ArrayBlockingQueue 默认情况下不能保证线程访问队列的公平性,所谓公平性是指严格按照线程等待的绝对时间顺序,即最先等待的线程能够最先访问到 ArrayBlockingQueue。而非公平性则是指访问 ArrayBlockingQueue 的顺序不是遵守严格的时间顺序,有可能存在,当 ArrayBlockingQueue 可以被访问时,长时间阻塞的线程依然无法访问到 ArrayBlockingQueue。如果保证公平性,通常会降低吞吐量。如果需要获得公平性的 ArrayBlockingQueue,可采用如下代码:
+`ArrayBlockingQueue` 默认情况下不能保证线程访问队列的公平性,所谓公平性是指严格按照线程等待的绝对时间顺序,即最先等待的线程能够最先访问到 `ArrayBlockingQueue`。而非公平性则是指访问 `ArrayBlockingQueue` 的顺序不是遵守严格的时间顺序,有可能存在,当 `ArrayBlockingQueue` 可以被访问时,长时间阻塞的线程依然无法访问到 `ArrayBlockingQueue`。如果保证公平性,通常会降低吞吐量。如果需要获得公平性的 `ArrayBlockingQueue`,可采用如下代码:
```java
private static ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue(10,true);
```
-### 5.3 LinkedBlockingQueue
+### LinkedBlockingQueue
-**LinkedBlockingQueue** 底层基于**单向链表**实现的阻塞队列,可以当做无界队列也可以当做有界队列来使用,同样满足 FIFO 的特性,与 ArrayBlockingQueue 相比起来具有更高的吞吐量,为了防止 LinkedBlockingQueue 容量迅速增,损耗大量内存。通常在创建 LinkedBlockingQueue 对象时,会指定其大小,如果未指定,容量等于 Integer.MAX_VALUE。
+`LinkedBlockingQueue` 底层基于**单向链表**实现的阻塞队列,可以当做无界队列也可以当做有界队列来使用,同样满足 FIFO 的特性,与 `ArrayBlockingQueue` 相比起来具有更高的吞吐量,为了防止 `LinkedBlockingQueue` 容量迅速增,损耗大量内存。通常在创建 `LinkedBlockingQueue` 对象时,会指定其大小,如果未指定,容量等于 `Integer.MAX_VALUE` 。
**相关构造方法:**
@@ -174,25 +156,21 @@ private static ArrayBlockingQueue blockingQueue = new ArrayBlockingQueu
}
```
-### 5.4 PriorityBlockingQueue
-
-**PriorityBlockingQueue** 是一个支持优先级的无界阻塞队列。默认情况下元素采用自然顺序进行排序,也可以通过自定义类实现 `compareTo()` 方法来指定元素排序规则,或者初始化时通过构造器参数 `Comparator` 来指定排序规则。
+### PriorityBlockingQueue
-PriorityBlockingQueue 并发控制采用的是 **ReentrantLock**,队列为无界队列(ArrayBlockingQueue 是有界队列,LinkedBlockingQueue 也可以通过在构造函数中传入 capacity 指定队列最大的容量,但是 PriorityBlockingQueue 只能指定初始的队列大小,后面插入元素的时候,**如果空间不够的话会自动扩容**)。
+`PriorityBlockingQueue` 是一个支持优先级的无界阻塞队列。默认情况下元素采用自然顺序进行排序,也可以通过自定义类实现 `compareTo()` 方法来指定元素排序规则,或者初始化时通过构造器参数 `Comparator` 来指定排序规则。
-简单地说,它就是 PriorityQueue 的线程安全版本。不可以插入 null 值,同时,插入队列的对象必须是可比较大小的(comparable),否则报 ClassCastException 异常。它的插入操作 put 方法不会 block,因为它是无界队列(take 方法在队列为空的时候会阻塞)。
+`PriorityBlockingQueue` 并发控制采用的是可重入锁 `ReentrantLock`,队列为无界队列(`ArrayBlockingQueue` 是有界队列,`LinkedBlockingQueue` 也可以通过在构造函数中传入 `capacity` 指定队列最大的容量,但是 `PriorityBlockingQueue` 只能指定初始的队列大小,后面插入元素的时候,**如果空间不够的话会自动扩容**)。
-**推荐文章:**
+简单地说,它就是 `PriorityQueue` 的线程安全版本。不可以插入 null 值,同时,插入队列的对象必须是可比较大小的(comparable),否则报 `ClassCastException` 异常。它的插入操作 put 方法不会 block,因为它是无界队列(take 方法在队列为空的时候会阻塞)。
-《解读 Java 并发队列 BlockingQueue》
+**推荐文章:** [《解读 Java 并发队列 BlockingQueue》](https://javadoop.com/post/java-concurrent-queue)
-[https://javadoop.com/post/java-concurrent-queue](https://javadoop.com/post/java-concurrent-queue "https://javadoop.com/post/java-concurrent-queue")
-
-## 六 ConcurrentSkipListMap
+## ConcurrentSkipListMap
下面这部分内容参考了极客时间专栏[《数据结构与算法之美》](https://time.geekbang.org/column/intro/126?code=zl3GYeAsRI4rEJIBNu5B/km7LSZsPDlGWQEpAYw5Vu0=&utm_term=SPoster "《数据结构与算法之美》")以及《实战 Java 高并发程序设计》。
-**为了引出 ConcurrentSkipListMap,先带着大家简单理解一下跳表。**
+为了引出 `ConcurrentSkipListMap`,先带着大家简单理解一下跳表。
对于一个单链表,即使链表是有序的,如果我们想要在其中查找某个数据,也只能从头到尾遍历链表,这样效率自然就会很低,跳表就不一样了。跳表是一种可以用来快速查找的数据结构,有点类似于平衡树。它们都可以对元素进行快速的查找。但一个重要的区别是:对平衡树的插入和删除往往很可能导致平衡树进行一次全局的调整。而对跳表的插入和删除只需要对整个数据结构的局部进行操作即可。这样带来的好处是:在高并发的情况下,你会需要一个全局锁来保证整个平衡树的线程安全。而对于跳表,你只需要部分锁即可。这样,在高并发环境下,你就可以拥有更好的性能。而就查询的性能而言,跳表的时间复杂度也是 **O(logn)** 所以在并发数据结构中,JDK 使用跳表来实现一个 Map。
@@ -210,20 +188,10 @@ PriorityBlockingQueue 并发控制采用的是 **ReentrantLock**,队列为无
从上面很容易看出,**跳表是一种利用空间换时间的算法。**
-使用跳表实现 Map 和使用哈希算法实现 Map 的另外一个不同之处是:哈希并不会保存元素的顺序,而跳表内所有的元素都是排序的。因此在对跳表进行遍历时,你会得到一个有序的结果。所以,如果你的应用需要有序性,那么跳表就是你不二的选择。JDK 中实现这一数据结构的类是 ConcurrentSkipListMap。
+使用跳表实现 `Map` 和使用哈希算法实现 `Map` 的另外一个不同之处是:哈希并不会保存元素的顺序,而跳表内所有的元素都是排序的。因此在对跳表进行遍历时,你会得到一个有序的结果。所以,如果你的应用需要有序性,那么跳表就是你不二的选择。JDK 中实现这一数据结构的类是 `ConcurrentSkipListMap`。
-## 七 参考
+## 参考
- 《实战 Java 高并发程序设计》
- https://javadoop.com/post/java-concurrent-queue
- https://juejin.im/post/5aeebd02518825672f19c546
-
-## 公众号
-
-如果大家想要实时关注我更新的文章以及分享的干货的话,可以关注我的公众号。
-
-**《Java 面试突击》:** 由本文档衍生的专为面试而生的《Java 面试突击》V2.0 PDF 版本[公众号](#公众号 "公众号")后台回复 **"面试突击"** 即可免费领取!
-
-**Java 工程师必备学习资源:** 一些 Java 工程师常用学习资源公众号后台回复关键字 **“1”** 即可免费无套路获取。
-
-
diff --git "a/docs/java/new-features/java\346\226\260\347\211\271\346\200\247\346\200\273\347\273\223.md" "b/docs/java/new-features/java\346\226\260\347\211\271\346\200\247\346\200\273\347\273\223.md"
new file mode 100644
index 00000000000..c815fa1ab7d
--- /dev/null
+++ "b/docs/java/new-features/java\346\226\260\347\211\271\346\200\247\346\200\273\347\273\223.md"
@@ -0,0 +1,948 @@
+Java 8 新特性见这里:[Java8 新特性最佳指南](https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&mid=2247484744&idx=1&sn=9db31dca13d327678845054af75efb74&chksm=cea24a83f9d5c3956f4feb9956b068624ab2fdd6c4a75fe52d5df5dca356a016577301399548&token=1082669959&lang=zh_CN&scene=21#wechat_redirect) 。
+
+你可以在 [Archived OpenJDK General-Availability Releases](http://jdk.java.net/archive/) 上下载自己需要的 JDK 版本!
+
+官方的新特性说明文档地址: https://openjdk.java.net/projects/jdk/ 。
+
+_Guide 哥:别人家的特性都用了几年了,我 Java 才出来,哈哈!真实!_
+
+## Java9
+
+发布于 2017 年 9 月 21 日 。作为 Java8 之后 3 年半才发布的新版本,Java 9 带 来了很多重大的变化其中最重要的改动是 Java 平台模块系统的引入,其他还有诸如集合、Stream 流
+
+### Java 平台模块系统
+
+Java 平台模块系统是[Jigsaw Project](https://openjdk.java.net/projects/jigsaw/)的一部分,把模块化开发实践引入到了 Java 平台中,可以让我们的代码可重用性更好!
+
+什么是模块系统?官方的定义是:A uniquely named, reusable group of related packages, as well as resources (such as images and XML files) and a module descriptor.
+
+简单来说,你可以将一个模块看作是一组唯一命名、可重用的包、资源和模块描述文件(module-info.java)。
+
+任意一个 jar 文件,只要加上一个 模块描述文件(module-info.java),就可以升级为一个模块。
+
+
+
+在引入了模块系统之后,JDK 被重新组织成 94 个模块。Java 应用可以通过新增的 jlink 工具,创建出只包含所依赖的 JDK 模块的自定义运行时镜像。这样可以极大的减少 Java 运行时环境的大小。
+
+我们可以通过 exports 关键词精准控制哪些类可以对外开放使用,哪些类只能内部使用。
+
+```java
+module my.module {
+ //exports 公开指定包的所有公共成员
+ exports com.my.package.name;
+}
+
+module my.module {
+ //exports…to 限制访问的成员范围
+ export com.my.package.name to com.specific.package;
+}
+```
+
+Java 9 模块的重要特征是在其工件(artifact)的根目录中包含了一个描述模块的 `module-info.java` 文 件。 工件的格式可以是传统的 JAR 文件或是 Java 9 新增的 JMOD 文件。
+
+想要深入了解 Java 9 的模块化,参见:
+
+- [《Project Jigsaw: Module System Quick-Start Guide》](https://openjdk.java.net/projects/jigsaw/quick-start)
+- [《Java 9 Modules: part 1》](https://stacktraceguru.com/java9/module-introduction)
+
+### Jshell
+
+jshell 是 Java 9 新增的一个实用工具。为 Java 提供了类似于 Python 的实时命令行交互工具。
+
+在 Jshell 中可以直接输入表达式并查看其执行结果。
+
+
+
+### 集合增强
+
+增加 了 `List.of()`、`Set.of()`、`Map.of()` 和 `Map.ofEntries()`等工厂方法来创建不可变集合(这部分内容有点参考 Guava 的味道)
+
+```java
+List.of("Java", "C++");
+Set.of("Java", "C++");
+Map.of("Java", 1, "C++", 2)`;
+```
+
+使用 `of()` 创建的集合为不可变集合,不能进行添加、删除、替换、 排序等操作,不然会报 `java.lang.UnsupportedOperationException` 异常。
+
+`Collectors` 中增加了新的方法 `filtering()` 和 `flatMapping()`。
+
+`Collectors` 的 `filtering()` 方法类似于 `Stream` 类的 `filter()` 方法,都是用于过滤元素。
+
+> Java 8 为 `Collectors` 类引入了 `groupingBy` 操作,用于根据特定的属性将对象分组。
+
+```java
+List list = List.of("x","www", "yy", "zz");
+Map> result = list.stream()
+ .collect(Collectors.groupingBy(String::length,
+ Collectors.filtering(s -> !s.contains("z"),
+ Collectors.toList())));
+
+System.out.println(result); // {1=[x], 2=[yy], 3=[www]}
+```
+
+### Stream & Optional 增强
+
+`Stream` 中增加了新的方法 `ofNullable()`、`dropWhile()`、`takeWhile()` 以及 `iterate()` 方法的重载方法。
+
+Java 9 中的 `ofNullable()` 方 法允许我们创建一个单元素的 `Stream`,可以包含一个非空元素,也可以创建一个空 `Stream`。 而在 Java 8 中则不可以创建空的 `Stream` 。
+
+```java
+Stream stringStream = Stream.ofNullable("Java");
+System.out.println(stringStream.count());// 1
+Stream nullStream = Stream.ofNullable(null);
+System.out.println(nullStream.count());//0
+```
+
+`takeWhile()` 方法可以从 `Stream` 中依次获取满足条件的元素,直到不满足条件为止结束获取。
+
+```java
+List integerList = List.of(11, 33, 66, 8, 9, 13);
+integerList.stream().takeWhile(x -> x < 50).forEach(System.out::println);// 11 33
+```
+
+`dropWhile()` 方法的效果和 `takeWhile()` 相反。
+
+```java
+List integerList2 = List.of(11, 33, 66, 8, 9, 13);
+integerList2.stream().dropWhile(x -> x < 50).forEach(System.out::println);// 66 8 9 13
+```
+
+`iterate()` 方法的新重载方法提供了一个 `Predicate` 参数 (判断条件)来决定什么时候结束迭代
+
+```java
+public static Stream iterate(final T seed, final UnaryOperator f) {
+}
+// 新增加的重载方法
+public static Stream iterate(T seed, Predicate super T> hasNext, UnaryOperator next) {
+
+}
+```
+
+两者的使用对比如下,新的 `iterate()` 重载方法更加灵活一些。
+
+```java
+// 使用原始 iterate() 方法输出数字 1~10
+Stream.iterate(1, i -> i + 1).limit(10).forEach(System.out::println);
+// 使用新的 iterate() 重载方法输出数字 1~10
+Stream.iterate(1, i -> i <= 10, i -> i + 1).forEach(System.out::println);
+```
+
+`Optional` 类中新增了 `ifPresentOrElse()`、`or()` 和 `stream()` 等方法
+
+`ifPresentOrElse()` 方法接受两个参数 `Consumer` 和 `Runnable` ,如果 `Optional` 不为空调用 `Consumer` 参数,为空则调用 `Runnable` 参数。
+
+```java
+public void ifPresentOrElse(Consumer super T> action, Runnable emptyAction)
+
+Optional