diff --git a/README.md b/README.md index 8e214899..4335494a 100644 --- a/README.md +++ b/README.md @@ -44,10 +44,10 @@ ### 基础 -**知识点/面试题:**(必看:+1: ) +**知识点/面试题** : (必看:+1: ) 1. **[Java 基础知识](docs/java/basis/Java基础知识.md)** -2. **[Java 基础知识疑难点/易错点](docs/java/basis/Java基础知识疑难点.md)** +2. [Java 基础知识疑难点/易错点](docs/java/basis/Java基础知识疑难点.md) **重要知识点详解:** @@ -61,6 +61,7 @@ 1. **[Java 容器常见问题总结](docs/java/collection/Java集合框架常见面试题.md)** (必看 :+1:) 2. **源码分析** :[ArrayList 源码+扩容机制分析](docs/java/collection/ArrayList源码+扩容机制分析.md) 、[LinkedList 源码](docs/java/collection/LinkedList源码分析.md) 、[HashMap(JDK1.8)源码+底层数据结构分析]() 、[ConcurrentHashMap 源码+底层数据结构分析](docs/java/collection/ConcurrentHashMap源码+底层数据结构分析.md) +3. [Java 容器使用注意事项总结](docs/java/collection/Java集合使用注意事项总结.md) ### 并发 @@ -71,11 +72,12 @@ **重要知识点详解:** -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) +6. [CompletableFuture入门](docs/java/multi-thread/CompletableFuture入门.md) ### JVM (必看 :+1:) @@ -95,28 +97,38 @@ 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~Java15** : [一文带你看遍 JDK9~15 的重要新特性!](./docs/java/new-features/java新特性总结.md) +### 小技巧 + +1. [JAD 反编译](docs/java/tips/JAD反编译tricks.md) +2. [手把手教你定位常见 Java 性能问题](./docs/java/tips/手把手教你定位常见Java性能问题.md) + ## 计算机基础 👉 **[图解计算机基础 PDF 下载](https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&mid=100021725&idx=1&sn=2db9664ca25363139a81691043e9fd8f&chksm=4ea19a1679d61300d8990f7e43bfc7f476577a81b712cf0f9c6f6552a8b219bc081efddb5c54#rd)** 。 ### 操作系统 -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 +137,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/dataStructures-algorithms/几道常见的字符串算法题.md) -- [几道常见的链表算法题总结 ](docs/dataStructures-algorithms/几道常见的链表算法题.md) -- [剑指 offer 部分编程题](docs/dataStructures-algorithms/剑指offer部分编程题.md) +- [几道常见的字符串算法题总结 ](docs/cs-basics/algorithms/几道常见的字符串算法题.md) +- [几道常见的链表算法题总结 ](docs/cs-basics/algorithms/几道常见的链表算法题.md) +- [剑指 offer 部分编程题](docs/cs-basics/algorithms/剑指offer部分编程题.md) + +另外,[GeeksforGeeks]( https://www.geeksforgeeks.org/fundamentals-of-algorithms/) 这个网站总结了常见的算法 ,比较全面系统。 ## 数据库 @@ -147,7 +161,7 @@ JVM 这部分内容主要参考 [JVM 虚拟机规范-Java8 ](https://docs.oracle 1. [MySQL数据库索引总结](docs/database/mysql/MySQL数据库索引.md) 2. [事务隔离级别(图文详解)](docs/database/mysql/事务隔离级别(图文详解).md) -3. [MySQL三大日志(binlog、redo log和undo log)详解](docs/database/mysql/MySQL三大日志(binlog、redo log和undo log).md) +3. [MySQL三大日志(binlog、redo log和undo log)详解](docs/database/mysql/MySQL三大日志.md) 4. [InnoDB存储引擎对MVCC的实现](docs/database/mysql/InnoDB对MVCC的实现.md) 5. [一条 SQL 语句在 MySQL 中如何执行的](docs/database/mysql/一条sql语句在mysql中如何执行的.md) 6. [关于数据库中如何存储时间的一点思考](docs/database/mysql/关于数据库存储时间的一点思考.md) @@ -264,7 +278,7 @@ Dubbo 是一款国产的 RPC 框架,由阿里开源。相关阅读: #### 分布式 id -在复杂分布式系统中,往往需要对大量的数据和消息进行唯一标识。比如数据量太大之后,往往需要对进行对数据进行分库分表,分库分表后需要有一个唯一 ID 来标识一条数据或消息,数据库的自增 ID 显然不能满足需求。相关阅读:[为什么要分布式 id ?分布式 id 生成方案有哪些?](docs/system-design/micro-service/分布式id生成方案总结.md) +在复杂分布式系统中,往往需要对大量的数据和消息进行唯一标识。比如数据量太大之后,往往需要对数据进行分库分表,分库分表后需要有一个唯一 ID 来标识一条数据或消息,数据库的自增 ID 显然不能满足需求。相关阅读:[为什么要分布式 id ?分布式 id 生成方案有哪些?](docs/system-design/micro-service/分布式id生成方案总结.md) #### 分布式事务 @@ -347,6 +361,24 @@ Dubbo 是一款国产的 RPC 框架,由阿里开源。相关阅读: 另外,重试的次数一般设为 3 次,再多次的重试没有好处,反而会加重服务器压力(部分场景使用失败重试机制会不太适合)。 +#### 灾备设计 + +**灾备** = 容灾+备份。 + +- **备份** : 将系统所产生的的所有重要数据多备份几份。 +- **容灾** : 在异地建立两个完全相同的系统。当某个地方的系统突然挂掉,整个应用系统可以切换到另一个,这样系统就可以正常提供服务了。 + +#### 异地多活 + +异地多活描述的是将服务部署在异地并且服务同时对外提供服务。和传统的灾备设计的最主要区别在于“多活”,即所有站点都是同时在对外提供服务的。 + +异地多活是为了应对突发状况比如火灾、地震等自然或者认为灾害。 + +相关阅读: + +- [四步构建异地多活](https://mp.weixin.qq.com/s/hMD-IS__4JE5_nQhYPYSTg) +- [《从零开始学架构》— 28 | 业务高可用的保障:异地多活架构](http://gk.link/a/10pKZ) + ### 大型网站架构 - [8 张图读懂大型网站技术架构](docs/system-design/website-architecture/8%20张图读懂大型网站技术架构.md) @@ -354,7 +386,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) @@ -378,7 +409,8 @@ Dubbo 是一款国产的 RPC 框架,由阿里开源。相关阅读: ### 待办 -- [ ] 数据结构总结重构 +- [ ] 计算机网络知识点完善 +- [ ] 分布式常见理论和算法总结完善 ### 捐赠支持 diff --git a/docs/dataStructures-algorithms/几道常见的字符串算法题.md b/docs/cs-basics/algorithms/几道常见的字符串算法题.md similarity index 100% rename from docs/dataStructures-algorithms/几道常见的字符串算法题.md rename to docs/cs-basics/algorithms/几道常见的字符串算法题.md diff --git a/docs/dataStructures-algorithms/几道常见的链表算法题.md b/docs/cs-basics/algorithms/几道常见的链表算法题.md similarity index 100% rename from docs/dataStructures-algorithms/几道常见的链表算法题.md rename to docs/cs-basics/algorithms/几道常见的链表算法题.md diff --git a/docs/dataStructures-algorithms/剑指offer部分编程题.md b/docs/cs-basics/algorithms/剑指offer部分编程题.md similarity index 100% rename from docs/dataStructures-algorithms/剑指offer部分编程题.md rename to docs/cs-basics/algorithms/剑指offer部分编程题.md diff --git a/docs/dataStructures-algorithms/data-structure/bloom-filter.md b/docs/cs-basics/data-structure/bloom-filter.md similarity index 73% rename from docs/dataStructures-algorithms/data-structure/bloom-filter.md rename to docs/cs-basics/data-structure/bloom-filter.md index bfb7efe7..ca6421e2 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 等数据结构,它占用空间更少并且效率更高,但是缺点是其返回的结果是概率性的,而不是非常准确的。理论情况下添加到集合中的元素越多,误报的可能性就越大。并且,存放在布隆过滤器的数据不容易删除。 ![布隆过滤器示意图](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-11/布隆过滤器-bit数组.png) -位数组中的每个元素都只占用 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 @@ 举个简单的例子: - - ![布隆过滤器hash计算](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-11/布隆过滤器-hash运算.png) -如图所示,当字符串存储要加入到布隆过滤器中时,该字符串首先由多个哈希函数生成不同的哈希值,然后将对应的位数组的下标设置为 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,18 @@ 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,35 +251,35 @@ 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 ...]` 。 -3. **`BF.EXISTS` ** : 确定元素是否在布隆过滤器中存在。格式:`BF.EXISTS {key} {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 ...]`。 另外,`BF.RESERVE` 命令需要单独介绍一下: 这个命令的格式如下: -`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 +293,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/图/图.png b/docs/cs-basics/data-structure/pictures/图/图.png similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/图/图.png rename to docs/cs-basics/data-structure/pictures/图/图.png diff --git a/docs/dataStructures-algorithms/data-structure/pictures/图/广度优先搜索1.drawio b/docs/cs-basics/data-structure/pictures/图/广度优先搜索1.drawio similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/图/广度优先搜索1.drawio rename to docs/cs-basics/data-structure/pictures/图/广度优先搜索1.drawio diff --git a/docs/dataStructures-algorithms/data-structure/pictures/图/广度优先搜索1.png b/docs/cs-basics/data-structure/pictures/图/广度优先搜索1.png similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/图/广度优先搜索1.png rename to docs/cs-basics/data-structure/pictures/图/广度优先搜索1.png diff --git a/docs/dataStructures-algorithms/data-structure/pictures/图/广度优先搜索2.drawio b/docs/cs-basics/data-structure/pictures/图/广度优先搜索2.drawio similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/图/广度优先搜索2.drawio rename to docs/cs-basics/data-structure/pictures/图/广度优先搜索2.drawio diff --git a/docs/dataStructures-algorithms/data-structure/pictures/图/广度优先搜索2.png b/docs/cs-basics/data-structure/pictures/图/广度优先搜索2.png similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/图/广度优先搜索2.png rename to docs/cs-basics/data-structure/pictures/图/广度优先搜索2.png diff --git a/docs/dataStructures-algorithms/data-structure/pictures/图/广度优先搜索3.drawio b/docs/cs-basics/data-structure/pictures/图/广度优先搜索3.drawio similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/图/广度优先搜索3.drawio rename to docs/cs-basics/data-structure/pictures/图/广度优先搜索3.drawio diff --git a/docs/dataStructures-algorithms/data-structure/pictures/图/广度优先搜索3.png b/docs/cs-basics/data-structure/pictures/图/广度优先搜索3.png similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/图/广度优先搜索3.png rename to docs/cs-basics/data-structure/pictures/图/广度优先搜索3.png diff --git a/docs/dataStructures-algorithms/data-structure/pictures/图/广度优先搜索4.drawio b/docs/cs-basics/data-structure/pictures/图/广度优先搜索4.drawio similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/图/广度优先搜索4.drawio rename to docs/cs-basics/data-structure/pictures/图/广度优先搜索4.drawio diff --git a/docs/dataStructures-algorithms/data-structure/pictures/图/广度优先搜索4.png b/docs/cs-basics/data-structure/pictures/图/广度优先搜索4.png similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/图/广度优先搜索4.png rename to docs/cs-basics/data-structure/pictures/图/广度优先搜索4.png diff --git a/docs/dataStructures-algorithms/data-structure/pictures/图/广度优先搜索5.drawio b/docs/cs-basics/data-structure/pictures/图/广度优先搜索5.drawio similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/图/广度优先搜索5.drawio rename to docs/cs-basics/data-structure/pictures/图/广度优先搜索5.drawio diff --git a/docs/dataStructures-algorithms/data-structure/pictures/图/广度优先搜索5.png b/docs/cs-basics/data-structure/pictures/图/广度优先搜索5.png similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/图/广度优先搜索5.png rename to docs/cs-basics/data-structure/pictures/图/广度优先搜索5.png diff --git a/docs/dataStructures-algorithms/data-structure/pictures/图/广度优先搜索6.drawio b/docs/cs-basics/data-structure/pictures/图/广度优先搜索6.drawio similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/图/广度优先搜索6.drawio rename to docs/cs-basics/data-structure/pictures/图/广度优先搜索6.drawio diff --git a/docs/dataStructures-algorithms/data-structure/pictures/图/广度优先搜索6.png b/docs/cs-basics/data-structure/pictures/图/广度优先搜索6.png similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/图/广度优先搜索6.png rename to docs/cs-basics/data-structure/pictures/图/广度优先搜索6.png diff --git a/docs/dataStructures-algorithms/data-structure/pictures/图/广度优先搜索图示.drawio b/docs/cs-basics/data-structure/pictures/图/广度优先搜索图示.drawio similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/图/广度优先搜索图示.drawio rename to docs/cs-basics/data-structure/pictures/图/广度优先搜索图示.drawio diff --git a/docs/dataStructures-algorithms/data-structure/pictures/图/广度优先搜索图示.png b/docs/cs-basics/data-structure/pictures/图/广度优先搜索图示.png similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/图/广度优先搜索图示.png rename to docs/cs-basics/data-structure/pictures/图/广度优先搜索图示.png diff --git a/docs/dataStructures-algorithms/data-structure/pictures/图/无向图的邻接矩阵存储.drawio b/docs/cs-basics/data-structure/pictures/图/无向图的邻接矩阵存储.drawio similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/图/无向图的邻接矩阵存储.drawio rename to docs/cs-basics/data-structure/pictures/图/无向图的邻接矩阵存储.drawio diff --git a/docs/dataStructures-algorithms/data-structure/pictures/图/无向图的邻接矩阵存储.png b/docs/cs-basics/data-structure/pictures/图/无向图的邻接矩阵存储.png similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/图/无向图的邻接矩阵存储.png rename to docs/cs-basics/data-structure/pictures/图/无向图的邻接矩阵存储.png diff --git a/docs/dataStructures-algorithms/data-structure/pictures/图/无向图的邻接表存储.drawio b/docs/cs-basics/data-structure/pictures/图/无向图的邻接表存储.drawio similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/图/无向图的邻接表存储.drawio rename to docs/cs-basics/data-structure/pictures/图/无向图的邻接表存储.drawio diff --git a/docs/dataStructures-algorithms/data-structure/pictures/图/无向图的邻接表存储.png b/docs/cs-basics/data-structure/pictures/图/无向图的邻接表存储.png similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/图/无向图的邻接表存储.png rename to docs/cs-basics/data-structure/pictures/图/无向图的邻接表存储.png diff --git a/docs/dataStructures-algorithms/data-structure/pictures/图/有向图的邻接矩阵存储.drawio b/docs/cs-basics/data-structure/pictures/图/有向图的邻接矩阵存储.drawio similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/图/有向图的邻接矩阵存储.drawio rename to docs/cs-basics/data-structure/pictures/图/有向图的邻接矩阵存储.drawio diff --git a/docs/dataStructures-algorithms/data-structure/pictures/图/有向图的邻接矩阵存储.png b/docs/cs-basics/data-structure/pictures/图/有向图的邻接矩阵存储.png similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/图/有向图的邻接矩阵存储.png rename to docs/cs-basics/data-structure/pictures/图/有向图的邻接矩阵存储.png diff --git a/docs/dataStructures-algorithms/data-structure/pictures/图/有向图的邻接矩阵存储的副本.drawio b/docs/cs-basics/data-structure/pictures/图/有向图的邻接矩阵存储的副本.drawio similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/图/有向图的邻接矩阵存储的副本.drawio rename to docs/cs-basics/data-structure/pictures/图/有向图的邻接矩阵存储的副本.drawio diff --git a/docs/dataStructures-algorithms/data-structure/pictures/图/有向图的邻接表存储.drawio b/docs/cs-basics/data-structure/pictures/图/有向图的邻接表存储.drawio similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/图/有向图的邻接表存储.drawio rename to docs/cs-basics/data-structure/pictures/图/有向图的邻接表存储.drawio diff --git a/docs/dataStructures-algorithms/data-structure/pictures/图/有向图的邻接表存储.png b/docs/cs-basics/data-structure/pictures/图/有向图的邻接表存储.png similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/图/有向图的邻接表存储.png rename to docs/cs-basics/data-structure/pictures/图/有向图的邻接表存储.png diff --git a/docs/dataStructures-algorithms/data-structure/pictures/图/深度优先搜索1.drawio b/docs/cs-basics/data-structure/pictures/图/深度优先搜索1.drawio similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/图/深度优先搜索1.drawio rename to docs/cs-basics/data-structure/pictures/图/深度优先搜索1.drawio diff --git a/docs/dataStructures-algorithms/data-structure/pictures/图/深度优先搜索1.png b/docs/cs-basics/data-structure/pictures/图/深度优先搜索1.png similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/图/深度优先搜索1.png rename to docs/cs-basics/data-structure/pictures/图/深度优先搜索1.png diff --git a/docs/dataStructures-algorithms/data-structure/pictures/图/深度优先搜索2.drawio b/docs/cs-basics/data-structure/pictures/图/深度优先搜索2.drawio similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/图/深度优先搜索2.drawio rename to docs/cs-basics/data-structure/pictures/图/深度优先搜索2.drawio diff --git a/docs/dataStructures-algorithms/data-structure/pictures/图/深度优先搜索2.png b/docs/cs-basics/data-structure/pictures/图/深度优先搜索2.png similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/图/深度优先搜索2.png rename to docs/cs-basics/data-structure/pictures/图/深度优先搜索2.png diff --git a/docs/dataStructures-algorithms/data-structure/pictures/图/深度优先搜索3.drawio b/docs/cs-basics/data-structure/pictures/图/深度优先搜索3.drawio similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/图/深度优先搜索3.drawio rename to docs/cs-basics/data-structure/pictures/图/深度优先搜索3.drawio diff --git a/docs/dataStructures-algorithms/data-structure/pictures/图/深度优先搜索3.png b/docs/cs-basics/data-structure/pictures/图/深度优先搜索3.png similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/图/深度优先搜索3.png rename to docs/cs-basics/data-structure/pictures/图/深度优先搜索3.png diff --git a/docs/dataStructures-algorithms/data-structure/pictures/图/深度优先搜索4.drawio b/docs/cs-basics/data-structure/pictures/图/深度优先搜索4.drawio similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/图/深度优先搜索4.drawio rename to docs/cs-basics/data-structure/pictures/图/深度优先搜索4.drawio diff --git a/docs/dataStructures-algorithms/data-structure/pictures/图/深度优先搜索4.png b/docs/cs-basics/data-structure/pictures/图/深度优先搜索4.png similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/图/深度优先搜索4.png rename to docs/cs-basics/data-structure/pictures/图/深度优先搜索4.png diff --git a/docs/dataStructures-algorithms/data-structure/pictures/图/深度优先搜索5.drawio b/docs/cs-basics/data-structure/pictures/图/深度优先搜索5.drawio similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/图/深度优先搜索5.drawio rename to docs/cs-basics/data-structure/pictures/图/深度优先搜索5.drawio diff --git a/docs/dataStructures-algorithms/data-structure/pictures/图/深度优先搜索5.png b/docs/cs-basics/data-structure/pictures/图/深度优先搜索5.png similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/图/深度优先搜索5.png rename to docs/cs-basics/data-structure/pictures/图/深度优先搜索5.png diff --git a/docs/dataStructures-algorithms/data-structure/pictures/图/深度优先搜索6.drawio b/docs/cs-basics/data-structure/pictures/图/深度优先搜索6.drawio similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/图/深度优先搜索6.drawio rename to docs/cs-basics/data-structure/pictures/图/深度优先搜索6.drawio diff --git a/docs/dataStructures-algorithms/data-structure/pictures/图/深度优先搜索6.png b/docs/cs-basics/data-structure/pictures/图/深度优先搜索6.png similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/图/深度优先搜索6.png rename to docs/cs-basics/data-structure/pictures/图/深度优先搜索6.png diff --git a/docs/dataStructures-algorithms/data-structure/pictures/图/深度优先搜索图示.drawio b/docs/cs-basics/data-structure/pictures/图/深度优先搜索图示.drawio similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/图/深度优先搜索图示.drawio rename to docs/cs-basics/data-structure/pictures/图/深度优先搜索图示.drawio diff --git a/docs/dataStructures-algorithms/data-structure/pictures/图/深度优先搜索图示.png b/docs/cs-basics/data-structure/pictures/图/深度优先搜索图示.png similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/图/深度优先搜索图示.png rename to docs/cs-basics/data-structure/pictures/图/深度优先搜索图示.png diff --git a/docs/dataStructures-algorithms/data-structure/pictures/堆/删除堆顶元素1.png b/docs/cs-basics/data-structure/pictures/堆/删除堆顶元素1.png similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/堆/删除堆顶元素1.png rename to docs/cs-basics/data-structure/pictures/堆/删除堆顶元素1.png diff --git a/docs/dataStructures-algorithms/data-structure/pictures/堆/删除堆顶元素2.png b/docs/cs-basics/data-structure/pictures/堆/删除堆顶元素2.png similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/堆/删除堆顶元素2.png rename to docs/cs-basics/data-structure/pictures/堆/删除堆顶元素2.png diff --git a/docs/dataStructures-algorithms/data-structure/pictures/堆/删除堆顶元素3.png b/docs/cs-basics/data-structure/pictures/堆/删除堆顶元素3.png similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/堆/删除堆顶元素3.png rename to docs/cs-basics/data-structure/pictures/堆/删除堆顶元素3.png diff --git a/docs/dataStructures-algorithms/data-structure/pictures/堆/删除堆顶元素4.png b/docs/cs-basics/data-structure/pictures/堆/删除堆顶元素4.png similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/堆/删除堆顶元素4.png rename to docs/cs-basics/data-structure/pictures/堆/删除堆顶元素4.png diff --git a/docs/dataStructures-algorithms/data-structure/pictures/堆/删除堆顶元素5.png b/docs/cs-basics/data-structure/pictures/堆/删除堆顶元素5.png similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/堆/删除堆顶元素5.png rename to docs/cs-basics/data-structure/pictures/堆/删除堆顶元素5.png diff --git a/docs/dataStructures-algorithms/data-structure/pictures/堆/删除堆顶元素6.png b/docs/cs-basics/data-structure/pictures/堆/删除堆顶元素6.png similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/堆/删除堆顶元素6.png rename to docs/cs-basics/data-structure/pictures/堆/删除堆顶元素6.png diff --git a/docs/dataStructures-algorithms/data-structure/pictures/堆/堆-插入元素1.png b/docs/cs-basics/data-structure/pictures/堆/堆-插入元素1.png similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/堆/堆-插入元素1.png rename to docs/cs-basics/data-structure/pictures/堆/堆-插入元素1.png diff --git a/docs/dataStructures-algorithms/data-structure/pictures/堆/堆-插入元素2.png b/docs/cs-basics/data-structure/pictures/堆/堆-插入元素2.png similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/堆/堆-插入元素2.png rename to docs/cs-basics/data-structure/pictures/堆/堆-插入元素2.png diff --git a/docs/dataStructures-algorithms/data-structure/pictures/堆/堆-插入元素3.png b/docs/cs-basics/data-structure/pictures/堆/堆-插入元素3.png similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/堆/堆-插入元素3.png rename to docs/cs-basics/data-structure/pictures/堆/堆-插入元素3.png diff --git a/docs/dataStructures-algorithms/data-structure/pictures/堆/堆1.png b/docs/cs-basics/data-structure/pictures/堆/堆1.png similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/堆/堆1.png rename to docs/cs-basics/data-structure/pictures/堆/堆1.png diff --git a/docs/dataStructures-algorithms/data-structure/pictures/堆/堆2.png b/docs/cs-basics/data-structure/pictures/堆/堆2.png similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/堆/堆2.png rename to docs/cs-basics/data-structure/pictures/堆/堆2.png diff --git a/docs/dataStructures-algorithms/data-structure/pictures/堆/堆排序1.png b/docs/cs-basics/data-structure/pictures/堆/堆排序1.png similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/堆/堆排序1.png rename to docs/cs-basics/data-structure/pictures/堆/堆排序1.png diff --git a/docs/dataStructures-algorithms/data-structure/pictures/堆/堆排序2.png b/docs/cs-basics/data-structure/pictures/堆/堆排序2.png similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/堆/堆排序2.png rename to docs/cs-basics/data-structure/pictures/堆/堆排序2.png diff --git a/docs/dataStructures-algorithms/data-structure/pictures/堆/堆排序3.png b/docs/cs-basics/data-structure/pictures/堆/堆排序3.png similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/堆/堆排序3.png rename to docs/cs-basics/data-structure/pictures/堆/堆排序3.png diff --git a/docs/dataStructures-algorithms/data-structure/pictures/堆/堆排序4.png b/docs/cs-basics/data-structure/pictures/堆/堆排序4.png similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/堆/堆排序4.png rename to docs/cs-basics/data-structure/pictures/堆/堆排序4.png diff --git a/docs/dataStructures-algorithms/data-structure/pictures/堆/堆排序5.png b/docs/cs-basics/data-structure/pictures/堆/堆排序5.png similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/堆/堆排序5.png rename to docs/cs-basics/data-structure/pictures/堆/堆排序5.png diff --git a/docs/dataStructures-algorithms/data-structure/pictures/堆/堆排序6.png b/docs/cs-basics/data-structure/pictures/堆/堆排序6.png similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/堆/堆排序6.png rename to docs/cs-basics/data-structure/pictures/堆/堆排序6.png diff --git a/docs/dataStructures-algorithms/data-structure/pictures/堆/堆的存储.png b/docs/cs-basics/data-structure/pictures/堆/堆的存储.png similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/堆/堆的存储.png rename to docs/cs-basics/data-structure/pictures/堆/堆的存储.png diff --git a/docs/dataStructures-algorithms/data-structure/pictures/堆/建堆1.png b/docs/cs-basics/data-structure/pictures/堆/建堆1.png similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/堆/建堆1.png rename to docs/cs-basics/data-structure/pictures/堆/建堆1.png diff --git a/docs/dataStructures-algorithms/data-structure/pictures/堆/建堆2.png b/docs/cs-basics/data-structure/pictures/堆/建堆2.png similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/堆/建堆2.png rename to docs/cs-basics/data-structure/pictures/堆/建堆2.png diff --git a/docs/dataStructures-algorithms/data-structure/pictures/堆/建堆3.png b/docs/cs-basics/data-structure/pictures/堆/建堆3.png similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/堆/建堆3.png rename to docs/cs-basics/data-structure/pictures/堆/建堆3.png diff --git a/docs/dataStructures-algorithms/data-structure/pictures/堆/建堆4.png b/docs/cs-basics/data-structure/pictures/堆/建堆4.png similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/堆/建堆4.png rename to docs/cs-basics/data-structure/pictures/堆/建堆4.png diff --git a/docs/cs-basics/data-structure/pictures/树/中序遍历.drawio b/docs/cs-basics/data-structure/pictures/树/中序遍历.drawio new file mode 100644 index 00000000..f8fe81d2 --- /dev/null +++ b/docs/cs-basics/data-structure/pictures/树/中序遍历.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/树/中序遍历.png b/docs/cs-basics/data-structure/pictures/树/中序遍历.png new file mode 100644 index 00000000..3ad5782c Binary files /dev/null and b/docs/cs-basics/data-structure/pictures/树/中序遍历.png differ diff --git a/docs/cs-basics/data-structure/pictures/树/中序遍历2.drawio b/docs/cs-basics/data-structure/pictures/树/中序遍历2.drawio new file mode 100644 index 00000000..31e3097a --- /dev/null +++ b/docs/cs-basics/data-structure/pictures/树/中序遍历2.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/树/中序遍历2.png b/docs/cs-basics/data-structure/pictures/树/中序遍历2.png new file mode 100644 index 00000000..fe6956b9 Binary files /dev/null and b/docs/cs-basics/data-structure/pictures/树/中序遍历2.png differ diff --git a/docs/cs-basics/data-structure/pictures/树/先序遍历.drawio b/docs/cs-basics/data-structure/pictures/树/先序遍历.drawio new file mode 100644 index 00000000..b92e5c29 --- /dev/null +++ b/docs/cs-basics/data-structure/pictures/树/先序遍历.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/树/先序遍历.png b/docs/cs-basics/data-structure/pictures/树/先序遍历.png new file mode 100644 index 00000000..5c80cedf Binary files /dev/null and b/docs/cs-basics/data-structure/pictures/树/先序遍历.png differ diff --git a/docs/cs-basics/data-structure/pictures/树/后序遍历.drawio b/docs/cs-basics/data-structure/pictures/树/后序遍历.drawio new file mode 100644 index 00000000..c324e801 --- /dev/null +++ b/docs/cs-basics/data-structure/pictures/树/后序遍历.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/树/后序遍历.png b/docs/cs-basics/data-structure/pictures/树/后序遍历.png new file mode 100644 index 00000000..87bf512e Binary files /dev/null and b/docs/cs-basics/data-structure/pictures/树/后序遍历.png differ diff --git a/docs/cs-basics/data-structure/pictures/树/完全二叉树.drawio b/docs/cs-basics/data-structure/pictures/树/完全二叉树.drawio new file mode 100644 index 00000000..107a75dd --- /dev/null +++ b/docs/cs-basics/data-structure/pictures/树/完全二叉树.drawio @@ -0,0 +1 @@ +5VpLc+I4EP41OoaynpaOPJzsZatSNYedOW0ZWwHvGMwYM8D8+m3bsrGMCQwhhAyVQ9QtoUf3p+5PDYgOZ5un1F9M/05CHSPihBtER4gQjB0B/3LNttRIRUrFJI1CM2in+BL90kbpGO0qCvXSGpglSZxFC1sZJPO5DjJL56dpsraHvSSxverCn+g9xZfAj/e1/0RhNjWnIO5O/5eOJtNqZSxU2TPzq8HmJMupHybrhop6iA7TJMnK1mwz1HFuvMou5eceD/TWG0v1PDvlA5GOgn9/JWv68PTfdumwH6Px8sHM8tOPV+bAiIgY5huMoTHJG/Dfny2gMR8vF6VcDHhJYF04VrY1thI/VknV8bAsPNmHAYQvNrvOalanmgY2XM5Ur1apGzsg1kIEDgb+B2GwnkaZ/rLwg7xnDRAE3TSbxSBhaPrLRQmKl2ijw3xvURwPkzhJi4noy4sWQQD6ZZYm33WjJ3TV2HHqxZtmrmym00xvGipj9iedzHSWbmGI6aXCQMDcAVLJ6waijGraAFOl8w2GJ/XMOzdDw3j6N7xOOrzeNvE87OfXB6R5Mte2WcEU6fZrU/jWFEb5uZ1a2hrpgrZfJqs00K+ckJpQ4acTnR3Hvw6tKLDvyYaneIenKl2qYz+Lftqxo8t9ZoXnJCouUQUUZgOF8xYCynObTzXvensi1ZrIaU1UGmZvogJN9bHPBxg9KaxcIIyQOwojTArLqZR/cBhhB728XPjz8526hxXc7c5aVy73Z3iZUOe2vMyvdZfpHd1lzG0vM/rBXhbX8jK/Iy8zzG7Ly+5bid8myr422t8qogftHevLhYr01VSxFm6NKrI/gyqKM6kid6SNUUauShXlWyHZ+RZxjgCsArLTADJ+Fci3CEl+W5Bs57SzXy9S9ohkxMWEuUwQTFuMqLv7SoBVlwLszUZEcSL86E3Bj1PVE5RyyiQH8oGxDUasegorxST0MOG450GTMfsNxtl1H9ZVWfT931zsjt5cFN8YG8ddddm3ErXX81t3WDqWR28xK1bOvJG4RB0rXWFlJzMX91zMXSJdDiFMtqY/OWXSzmmqRVjnFq4Vs8jBmHXht6W4o7clF7cWs7qKvm9n8pcnRjX372GXNx+yPaeWD8RIEJ51GoHBdGp058ez6l58Mp7FlOwpIYjCDgOqJbkNQ+H0uMvyb0g5kVxwcV5A49QmWuzaROtwcfvCQcu9o6DV/lrqo2vb+HBx+8J0Wt4Rna5/8tCuTX2Ym7uq2+e92Xv805SZjhNl1plYTkhd/CMTEJbwlFc113WlXWTnGBK50ygPnZmBsBA9Lg5WoTilPUZ3u7gyp36PSv7VkLkHuONQ5Z8BmZRdBZntcsVe7f+dwSc6wOdxNPBQ30MeQ4NH1MfIEwjSvRoijyBZNGy6FNSI2SVPQJVSlO7n06com67G+ZzSQ0oiTyHpIgWryHzRfDmOpESKHGJTZhejOjOnp2R3zDqzOyymBkh5eaPPkBxd5JDPo8eju4fzggWANObnfURKmL2A8XNTuKhPGzZx84ZyC18M0aBfDH4sGm4+oMq4jagBOT6zQ4V9wU0oaUYDo/LjaDIHMYDrnj+PBjljiAI/7puOWRSG8SEWkyareZhzliLYxP5YxwM/+D4p9O3FwTTmp6KQw0q5EYAGxd+FSoPuccpa851mSCG/T2ZA3P0ctLysux/VUu9/ \ No newline at end of file diff --git a/docs/cs-basics/data-structure/pictures/树/完全二叉树.png b/docs/cs-basics/data-structure/pictures/树/完全二叉树.png new file mode 100644 index 00000000..bc0fe0dc Binary files /dev/null and b/docs/cs-basics/data-structure/pictures/树/完全二叉树.png differ diff --git a/docs/cs-basics/data-structure/pictures/树/平衡二叉树.drawio b/docs/cs-basics/data-structure/pictures/树/平衡二叉树.drawio new file mode 100644 index 00000000..11133b53 --- /dev/null +++ b/docs/cs-basics/data-structure/pictures/树/平衡二叉树.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/树/平衡二叉树.png b/docs/cs-basics/data-structure/pictures/树/平衡二叉树.png new file mode 100644 index 00000000..673f3e32 Binary files /dev/null and b/docs/cs-basics/data-structure/pictures/树/平衡二叉树.png differ diff --git a/docs/cs-basics/data-structure/pictures/树/斜树.drawio b/docs/cs-basics/data-structure/pictures/树/斜树.drawio new file mode 100644 index 00000000..6eeaa610 --- /dev/null +++ b/docs/cs-basics/data-structure/pictures/树/斜树.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/树/斜树.png b/docs/cs-basics/data-structure/pictures/树/斜树.png new file mode 100644 index 00000000..af129158 Binary files /dev/null and b/docs/cs-basics/data-structure/pictures/树/斜树.png differ diff --git a/docs/cs-basics/data-structure/pictures/树/满二叉树.drawio b/docs/cs-basics/data-structure/pictures/树/满二叉树.drawio new file mode 100644 index 00000000..8379028d --- /dev/null +++ b/docs/cs-basics/data-structure/pictures/树/满二叉树.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/树/满二叉树.png b/docs/cs-basics/data-structure/pictures/树/满二叉树.png new file mode 100644 index 00000000..c0f30c04 Binary files /dev/null and b/docs/cs-basics/data-structure/pictures/树/满二叉树.png differ diff --git a/docs/cs-basics/data-structure/pictures/树/链式存储二叉树.drawio b/docs/cs-basics/data-structure/pictures/树/链式存储二叉树.drawio new file mode 100644 index 00000000..37585459 --- /dev/null +++ b/docs/cs-basics/data-structure/pictures/树/链式存储二叉树.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/树/链式存储二叉树.png b/docs/cs-basics/data-structure/pictures/树/链式存储二叉树.png new file mode 100644 index 00000000..c0ce15b7 Binary files /dev/null and b/docs/cs-basics/data-structure/pictures/树/链式存储二叉树.png differ diff --git a/docs/cs-basics/data-structure/pictures/树/顺序存储.drawio b/docs/cs-basics/data-structure/pictures/树/顺序存储.drawio new file mode 100644 index 00000000..1ddbb02d --- /dev/null +++ b/docs/cs-basics/data-structure/pictures/树/顺序存储.drawio @@ -0,0 +1 @@ +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 \ No newline at end of file diff --git a/docs/cs-basics/data-structure/pictures/树/顺序存储.png b/docs/cs-basics/data-structure/pictures/树/顺序存储.png new file mode 100644 index 00000000..33f3c6e3 Binary files /dev/null and b/docs/cs-basics/data-structure/pictures/树/顺序存储.png differ diff --git a/docs/cs-basics/data-structure/pictures/树/顺序存储2.drawio b/docs/cs-basics/data-structure/pictures/树/顺序存储2.drawio new file mode 100644 index 00000000..8048a1a7 --- /dev/null +++ b/docs/cs-basics/data-structure/pictures/树/顺序存储2.drawio @@ -0,0 +1 @@ +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 \ No newline at end of file diff --git a/docs/cs-basics/data-structure/pictures/树/顺序存储2.png b/docs/cs-basics/data-structure/pictures/树/顺序存储2.png new file mode 100644 index 00000000..70c6da26 Binary files /dev/null and b/docs/cs-basics/data-structure/pictures/树/顺序存储2.png differ diff --git a/docs/dataStructures-algorithms/data-structure/pictures/线性数据结构/单链表2.png b/docs/cs-basics/data-structure/pictures/线性数据结构/单链表2.png similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/线性数据结构/单链表2.png rename to docs/cs-basics/data-structure/pictures/线性数据结构/单链表2.png diff --git a/docs/dataStructures-algorithms/data-structure/pictures/线性数据结构/双向循环链表.png b/docs/cs-basics/data-structure/pictures/线性数据结构/双向循环链表.png similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/线性数据结构/双向循环链表.png rename to docs/cs-basics/data-structure/pictures/线性数据结构/双向循环链表.png diff --git a/docs/dataStructures-algorithms/data-structure/pictures/线性数据结构/双向链表.png b/docs/cs-basics/data-structure/pictures/线性数据结构/双向链表.png similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/线性数据结构/双向链表.png rename to docs/cs-basics/data-structure/pictures/线性数据结构/双向链表.png diff --git a/docs/dataStructures-algorithms/data-structure/pictures/线性数据结构/循环队列-堆满.png b/docs/cs-basics/data-structure/pictures/线性数据结构/循环队列-堆满.png similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/线性数据结构/循环队列-堆满.png rename to docs/cs-basics/data-structure/pictures/线性数据结构/循环队列-堆满.png diff --git a/docs/dataStructures-algorithms/data-structure/pictures/线性数据结构/数组.png b/docs/cs-basics/data-structure/pictures/线性数据结构/数组.png similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/线性数据结构/数组.png rename to docs/cs-basics/data-structure/pictures/线性数据结构/数组.png diff --git a/docs/dataStructures-algorithms/data-structure/pictures/线性数据结构/栈.png b/docs/cs-basics/data-structure/pictures/线性数据结构/栈.png similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/线性数据结构/栈.png rename to docs/cs-basics/data-structure/pictures/线性数据结构/栈.png diff --git a/docs/dataStructures-algorithms/data-structure/pictures/线性数据结构/栈实现浏览器倒退和前进.drawio b/docs/cs-basics/data-structure/pictures/线性数据结构/栈实现浏览器倒退和前进.drawio similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/线性数据结构/栈实现浏览器倒退和前进.drawio rename to docs/cs-basics/data-structure/pictures/线性数据结构/栈实现浏览器倒退和前进.drawio diff --git a/docs/dataStructures-algorithms/data-structure/pictures/线性数据结构/栈实现浏览器倒退和前进.png b/docs/cs-basics/data-structure/pictures/线性数据结构/栈实现浏览器倒退和前进.png similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/线性数据结构/栈实现浏览器倒退和前进.png rename to docs/cs-basics/data-structure/pictures/线性数据结构/栈实现浏览器倒退和前进.png diff --git a/docs/dataStructures-algorithms/data-structure/pictures/线性数据结构/队列.png b/docs/cs-basics/data-structure/pictures/线性数据结构/队列.png similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/线性数据结构/队列.png rename to docs/cs-basics/data-structure/pictures/线性数据结构/队列.png diff --git a/docs/dataStructures-algorithms/data-structure/pictures/线性数据结构/顺序队列假溢出.png b/docs/cs-basics/data-structure/pictures/线性数据结构/顺序队列假溢出.png similarity index 100% rename from docs/dataStructures-algorithms/data-structure/pictures/线性数据结构/顺序队列假溢出.png rename to docs/cs-basics/data-structure/pictures/线性数据结构/顺序队列假溢出.png diff --git a/docs/dataStructures-algorithms/data-structure/图.md b/docs/cs-basics/data-structure/图.md similarity index 100% rename from docs/dataStructures-algorithms/data-structure/图.md rename to docs/cs-basics/data-structure/图.md diff --git a/docs/dataStructures-algorithms/data-structure/堆.md b/docs/cs-basics/data-structure/堆.md similarity index 99% rename from docs/dataStructures-algorithms/data-structure/堆.md rename to docs/cs-basics/data-structure/堆.md index 7e8f9811..cd186132 100644 --- a/docs/dataStructures-algorithms/data-structure/堆.md +++ b/docs/cs-basics/data-structure/堆.md @@ -1,4 +1,7 @@ +# 堆 + ## 什么是堆 + 堆是一种满足以下条件的树: 堆中的每一个节点值都大于等于(或小于等于)子树中所有节点的值。或者说,任意一个节点的值都大于等于(或小于等于)所有子节点的值。 diff --git a/docs/cs-basics/data-structure/树.md b/docs/cs-basics/data-structure/树.md new file mode 100644 index 00000000..010cff99 --- /dev/null +++ b/docs/cs-basics/data-structure/树.md @@ -0,0 +1,174 @@ +# 树 + +树就是一种类似现实生活中的树的数据结构(倒置的树)。任何一颗非空树只有一个根节点。 + +一棵树具有以下特点: + +1. 一棵树中的任意两个结点有且仅有唯一的一条路径连通。 +2. 一棵树如果有 n 个结点,那么它一定恰好有 n-1 条边。 +3. 一棵树不包含回路。 + +下图就是一颗树,并且是一颗二叉树。 + +![二叉树](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-6/二叉树-2.png) + +如上图所示,通过上面这张图说明一下树中的常用概念: + +- **节点** :树中的每个元素都可以统称为节点。 +- **根节点** :顶层节点或者说没有父节点的节点。上图中 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 ,则它就是 **满二叉树**。如下图所示: + +![](./pictures/树/满二叉树.png) + +### 完全二叉树 + +除最后一层外,若其余层都是满的,并且最后一层或者是满的,或者是在右边缺少连续若干节点,则这个二叉树就是 **完全二叉树** 。 + +大家可以想象为一棵树从根结点开始扩展,扩展完左子节点才能开始扩展右子节点,每扩展完一层,才能继续扩展下一层。如下图所示: + +![](./pictures/树/完全二叉树.png) + +完全二叉树有一个很好的性质:**父结点和子节点的序号有着对应关系。** + +细心的小伙伴可能发现了,当根节点的值为 1 的情况下,若父结点的序号是 i,那么左子节点的序号就是 2i,右子节点的序号是 2i+1。这个性质使得完全二叉树利用数组存储时可以极大地节省空间,以及利用序号找到某个节点的父结点和子节点,后续二叉树的存储会详细介绍。 + +### 平衡二叉树 + +**平衡二叉树** 是一棵二叉排序树,且具有以下性质: + +1. 可以是一棵空树 +2. 如果不是空树,它的左右两个子树的高度差的绝对值不超过 1,并且左右两个子树都是一棵平衡二叉树。 + +平衡二叉树的常用实现方法有 **红黑树**、**AVL 树**、**替罪羊树**、**加权平衡树**、**伸展树** 等。 + +在给大家展示平衡二叉树之前,先给大家看一棵树: + +![](./pictures/树/斜树.png) + +**你管这玩意儿叫树???** + +没错,这玩意儿还真叫树,只不过这棵树已经退化为一个链表了,我们管它叫 **斜树**。 + +**如果这样,那我为啥不直接用链表呢?** + +谁说不是呢? + +二叉树相比于链表,由于父子节点以及兄弟节点之间往往具有某种特殊的关系,这种关系使得我们在树中对数据进行**搜索**和**修改**时,相对于链表更加快捷便利。 + +但是,如果二叉树退化为一个链表了,那么那么树所具有的优秀性质就难以表现出来,效率也会大打折,为了避免这样的情况,我们希望每个做 “家长”(父结点) 的,都 **一碗水端平**,分给左儿子和分给右儿子的尽可能一样多,相差最多不超过一层,如下图所示: + +![](./pictures/树/平衡二叉树.png) + +## 二叉树的存储 + +二叉树的存储主要分为 **链式存储** 和 **顺序存储** 两种: + +### 链式存储 + +和链表类似,二叉树的链式存储依靠指针将各个节点串联起来,不需要连续的存储空间。 + +每个节点包括三个属性: + +- 数据 data。data 不一定是单一的数据,根据不同情况,可以是多个具有不同类型的数据。 +- 左节点指针 left +- 右节点指针 right。 + +可是 JAVA 没有指针啊! + +那就直接引用对象呗(别问我对象哪里找) + +![](./pictures/树/链式存储二叉树.png) + +### 顺序存储 + +顺序存储就是利用数组进行存储,数组中的每一个位置仅存储节点的 data,不存储左右子节点的指针,子节点的索引通过数组下标完成。根结点的序号为 1,对于每个节点 Node,假设它存储在数组中下标为 i 的位置,那么它的左子节点就存储在 2 _ i 的位置,它的右子节点存储在下标为 2 _ i+1 的位置。 + +一棵完全二叉树的数组顺序存储如下图所示: + +![](./pictures/树/顺序存储.png) + +大家可以试着填写一下存储如下二叉树的数组,比较一下和完全二叉树的顺序存储有何区别: + +![](./pictures/树/顺序存储2.png) + +可以看到,如果我们要存储的二叉树不是完全二叉树,在数组中就会出现空隙,导致内存利用率降低 + +## 二叉树的遍历 + +### 先序遍历 + +![](./pictures/树/先序遍历.png) + +二叉树的先序遍历,就是先输出根结点,再遍历左子树,最后遍历右子树,遍历左子树和右子树的时候,同样遵循先序遍历的规则,也就是说,我们可以递归实现先序遍历。 + +代码如下: + +```java +public void preOrder(TreeNode root){ + if(root == null){ + return; + } + system.out.println(root.data); + preOrder(root.left); + preOrder(root.right); +} +``` + +### 中序遍历 + +![](./pictures/树/中序遍历.png) + +二叉树的中序遍历,就是先递归中序遍历左子树,再输出根结点的值,再递归中序遍历右子树,大家可以想象成一巴掌把树压扁,父结点被拍到了左子节点和右子节点的中间,如下图所示: + +![](./pictures/树/中序遍历2.png) + +代码如下: + +```java +public void inOrder(TreeNode root){ + if(root == null){ + return; + } + inOrder(root.left); + system.out.println(root.data); + inOrder(root.right); +} +``` + +### 后序遍历 + +![](./pictures/树/后序遍历.png) + +二叉树的后序遍历,就是先递归后序遍历左子树,再递归后序遍历右子树,最后输出根结点的值 + +代码如下: + +```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/红黑树.md b/docs/cs-basics/data-structure/红黑树.md new file mode 100644 index 00000000..1f13744f --- /dev/null +++ b/docs/cs-basics/data-structure/红黑树.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/线性数据结构.md b/docs/cs-basics/data-structure/线性数据结构.md similarity index 100% rename from docs/dataStructures-algorithms/data-structure/线性数据结构.md rename to docs/cs-basics/data-structure/线性数据结构.md diff --git a/docs/network/HTTPS中的TLS.md b/docs/cs-basics/network/HTTPS中的TLS.md similarity index 100% rename from docs/network/HTTPS中的TLS.md rename to docs/cs-basics/network/HTTPS中的TLS.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/七层体系结构图.png b/docs/cs-basics/network/images/七层体系结构图.png similarity index 100% rename from docs/network/images/七层体系结构图.png rename to docs/cs-basics/network/images/七层体系结构图.png diff --git a/docs/network/images/传输层.png b/docs/cs-basics/network/images/传输层.png similarity index 100% rename from docs/network/images/传输层.png rename to docs/cs-basics/network/images/传输层.png diff --git a/docs/network/images/应用层.png b/docs/cs-basics/network/images/应用层.png similarity index 100% rename from docs/network/images/应用层.png rename to docs/cs-basics/network/images/应用层.png diff --git a/docs/network/images/数据链路层.png b/docs/cs-basics/network/images/数据链路层.png similarity index 100% rename from docs/network/images/数据链路层.png rename to docs/cs-basics/network/images/数据链路层.png diff --git a/docs/network/images/物理层.png b/docs/cs-basics/network/images/物理层.png similarity index 100% rename from docs/network/images/物理层.png rename to docs/cs-basics/network/images/物理层.png diff --git a/docs/network/images/网络层.png b/docs/cs-basics/network/images/网络层.png similarity index 100% rename from docs/network/images/网络层.png rename to docs/cs-basics/network/images/网络层.png diff --git a/docs/network/images/计算机网络知识点总结/万维网的大致工作工程.png b/docs/cs-basics/network/images/计算机网络知识点总结/万维网的大致工作工程.png similarity index 100% rename from docs/network/images/计算机网络知识点总结/万维网的大致工作工程.png rename to docs/cs-basics/network/images/计算机网络知识点总结/万维网的大致工作工程.png diff --git a/docs/network/计算机网络.md b/docs/cs-basics/network/计算机网络.md similarity index 100% rename from docs/network/计算机网络.md rename to docs/cs-basics/network/计算机网络.md diff --git a/docs/network/计算机网络知识总结.md b/docs/cs-basics/network/计算机网络知识总结.md similarity index 100% rename from docs/network/计算机网络知识总结.md rename to docs/cs-basics/network/计算机网络知识总结.md diff --git a/docs/operating-system/Shell.md b/docs/cs-basics/operating-system/Shell.md similarity index 97% rename from docs/operating-system/Shell.md rename to docs/cs-basics/operating-system/Shell.md index 099bcaf6..0a7c1508 100644 --- a/docs/operating-system/Shell.md +++ b/docs/cs-basics/operating-system/Shell.md @@ -57,7 +57,7 @@ W3Cschool 上的一篇文章是这样介绍 Shell的,如下图所示。 ### Shell 编程的 Hello World -学习任何一门编程语言第一件事就是输出HelloWord了!下面我会从新建文件到shell代码编写来说下Shell 编程如何输出Hello World。 +学习任何一门编程语言第一件事就是输出HelloWorld了!下面我会从新建文件到shell代码编写来说下Shell 编程如何输出Hello World。 (1)新建一个文件 helloworld.sh :`touch helloworld.sh`,扩展名为 sh(sh代表Shell)(扩展名并不影响脚本执行,见名知意就好,如果你用 php 写 shell 脚本,扩展名就用 php 好了) @@ -94,14 +94,14 @@ shell中 # 符号表示注释。**shell 的第一行比较特殊,一般都会 3. **Shell变量** :Shell变量是由 Shell 程序设置的特殊变量。Shell 变量中有一部分是环境变量,有一部分是局部变量,这些变量保证了 Shell 的正常运行 **常用的环境变量:** -> PATH 决定了shell将到哪些目录中寻找命令或程序 -HOME 当前用户主目录 -HISTSIZE 历史记录数 -LOGNAME 当前用户的登录名 -HOSTNAME 指主机的名称 -SHELL 当前用户Shell类型 -LANGUGE  语言相关的环境变量,多语言可以修改此环境变量 -MAIL 当前用户的邮件存放目录 +> PATH 决定了shell将到哪些目录中寻找命令或程序 +HOME 当前用户主目录 +HISTSIZE 历史记录数 +LOGNAME 当前用户的登录名 +HOSTNAME 指主机的名称 +SHELL 当前用户Shell类型 +LANGUAGE  语言相关的环境变量,多语言可以修改此环境变量 +MAIL 当前用户的邮件存放目录 PS1 基本提示符,对于root用户是#,对于普通用户是$ **使用 Linux 已定义的环境变量:** 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之父.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/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/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/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/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/修改文件权限.png b/docs/cs-basics/operating-system/images/修改文件权限.png similarity index 100% rename from docs/operating-system/images/修改文件权限.png rename to docs/cs-basics/operating-system/images/修改文件权限.png diff --git a/docs/operating-system/images/文件inode信息.png b/docs/cs-basics/operating-system/images/文件inode信息.png similarity index 100% rename from docs/operating-system/images/文件inode信息.png rename to docs/cs-basics/operating-system/images/文件inode信息.png diff --git a/docs/operating-system/images/用户态与内核态.png b/docs/cs-basics/operating-system/images/用户态与内核态.png similarity index 100% rename from docs/operating-system/images/用户态与内核态.png rename to docs/cs-basics/operating-system/images/用户态与内核态.png diff --git a/docs/operating-system/linux.md b/docs/cs-basics/operating-system/linux.md similarity index 99% rename from docs/operating-system/linux.md rename to docs/cs-basics/operating-system/linux.md index 80b52fba..87d4f937 100644 --- a/docs/operating-system/linux.md +++ b/docs/cs-basics/operating-system/linux.md @@ -224,7 +224,7 @@ Linux 支持很多文件类型,其中非常重要的文件类型有: **普通 - **普通文件(-)** : 用于存储信息和数据, Linux 用户可以根据访问权限对普通文件进行查看、更改和删除。比如:图片、声音、PDF、text、视频、源代码等等。 - **目录文件(d,directory file)** :目录也是文件的一种,用于表示和管理系统中的文件,目录文件中包含一些文件名和子目录名。打开目录事实上就是打开目录文件。 - **符号链接文件(l,symbolic link)** :保留了指向文件的地址而不是文件本身。 -- **字符设备(c,char)** :用来访问字符设备比如硬盘。 +- **字符设备(c,char)** :用来访问字符设备比如键盘。 - **设备文件(b,block)** : 用来访问块设备比如硬盘、软盘。 - **管道文件(p,pipe)** : 一种特殊类型的文件,用于进程之间的通信。 - **套接字(s,socket)** :用于进程间的网络通信,也可以用于本机之间的非网络通信。 diff --git a/docs/dataStructures-algorithms/数据结构.md b/docs/dataStructures-algorithms/数据结构.md deleted file mode 100644 index 5caffaac..00000000 --- a/docs/dataStructures-algorithms/数据结构.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 93227374..74d0d6b0 100644 --- a/docs/database/Redis/redis-all.md +++ b/docs/database/Redis/redis-all.md @@ -743,7 +743,7 @@ _为什么会出现误判的情况呢? 我们还要从布隆过滤器的原理 然后,一定会出现这样一种情况:**不同的字符串可能哈希出来的位置相同。** (可以适当增加位数组大小或者调整我们的哈希函数来降低概率) -更多关于布隆过滤器的内容可以看我的这篇原创:[《不了解布隆过滤器?一文给你整的明明白白!》](https://github.com/Snailclimb/JavaGuide/blob/master/docs/dataStructures-algorithms/data-structure/bloom-filter.md) ,强烈推荐,个人感觉网上应该找不到总结的这么明明白白的文章了。 +更多关于布隆过滤器的内容可以看我的这篇原创:[《不了解布隆过滤器?一文给你整的明明白白!》](https://github.com/Snailclimb/JavaGuide/blob/master/docs/cs-basics/data-structure/bloom-filter.md) ,强烈推荐,个人感觉网上应该找不到总结的这么明明白白的文章了。 ### 缓存雪崩 diff --git a/docs/database/mysql/InnoDB对MVCC的实现.md b/docs/database/mysql/InnoDB对MVCC的实现.md index e846088d..4e929cd8 100644 --- a/docs/database/mysql/InnoDB对MVCC的实现.md +++ b/docs/database/mysql/InnoDB对MVCC的实现.md @@ -56,6 +56,24 @@ ### ReadView +```c +class ReadView { + /* ... */ +private: + trx_id_t m_low_limit_id; /* 大于这个 ID 的事务均不可见 */ + + trx_id_t m_up_limit_id; /* 小于这个 ID 的事务均可见 */ + + trx_id_t m_creator_trx_id; /* 创建该 Read View 的事务ID */ + + trx_id_t m_low_limit_no; /* 事务 Number, 小于该 Number 的 Undo Logs 均可以被 Purge */ + + ids_t m_ids; /* 创建 Read View 时的活跃事务列表 */ + + m_closed; /* 标记 Read View 是否 close */ +} +``` + [`Read View`](https://github.com/facebook/mysql-8.0/blob/8.0/storage/innobase/include/read0types.h#L298) 主要是用来做可见性判断,里面保存了 “当前对本事务不可见的其他活跃事务” 主要有以下字段: @@ -65,6 +83,10 @@ - `m_ids`:`Read View` 创建时其他未提交的活跃事务 ID 列表。创建 `Read View`时,将当前未提交事务 ID 记录下来,后续即使它们修改了记录行的值,对于当前事务也是不可见的。`m_ids` 不包括当前事务自己和已提交的事务(正在内存中) - `m_creator_trx_id`:创建该 `Read View` 的事务 ID +**事务可见性示意图**([图源](https://leviathan.vip/2019/03/20/InnoDB%E7%9A%84%E4%BA%8B%E5%8A%A1%E5%88%86%E6%9E%90-MVCC/#MVCC-1)): + +![trans_visible](https://leviathan.vip/2019/03/20/InnoDB%E7%9A%84%E4%BA%8B%E5%8A%A1%E5%88%86%E6%9E%90-MVCC/trans_visible.jpg) + ### undo-log `undo log` 主要有两个作用: @@ -90,7 +112,7 @@ ![](https://ddmcc-1255635056.file.myqcloud.com/6a276e7a-b0da-4c7b-bdf7-c0c7b7b3b31c.png) -不同事务或者相同事务的对同一记录行的修改,会使该记录行的 `undo log` 成为一条链表,链首就是最新的记录,链尾就是最早的旧记录 +不同事务或者相同事务的对同一记录行的修改,会使该记录行的 `undo log` 成为一条链表,链首就是最新的记录,链尾就是最早的旧记录。 ### 数据可见性算法 @@ -98,7 +120,7 @@ [具体的比较算法](https://github.com/facebook/mysql-8.0/blob/8.0/storage/innobase/include/read0types.h#L161)如下:[图源](https://leviathan.vip/2019/03/20/InnoDB%E7%9A%84%E4%BA%8B%E5%8A%A1%E5%88%86%E6%9E%90-MVCC/#MVCC-1) -![markdown](https://ddmcc-1255635056.file.myqcloud.com/8778836b-34a8-480b-b8c7-654fe207a8c2.png) +![](https://ddmcc-1255635056.file.myqcloud.com/8778836b-34a8-480b-b8c7-654fe207a8c2.png) 1. 如果记录 DB_TRX_ID < m_up_limit_id,那么表明最新修改该行的事务(DB_TRX_ID)在当前事务创建快照之前就提交了,所以该记录行的值对当前事务是可见的 @@ -106,7 +128,7 @@ 3. m_ids 为空,则表明在当前事务创建快照之前,修改该行的事务就已经提交了,所以该记录行的值对当前事务是可见的 -4. 如果 m_up_limit_id <= DB_TRX_ID < m_up_limit_id,表明最新修改该行的事务(DB_TRX_ID)在当前事务创建快照的时候可能处于“活动状态”或者“已提交状态”;所以就要对活跃事务列表 m_ids 进行查找(源码中是用的二分查找,因为是有序的) +4. 如果 m_low_limit_id <= DB_TRX_ID < m_up_limit_id,表明最新修改该行的事务(DB_TRX_ID)在当前事务创建快照的时候可能处于“活动状态”或者“已提交状态”;所以就要对活跃事务列表 m_ids 进行查找(源码中是用的二分查找,因为是有序的) - 如果在活跃事务列表 m_ids 中能找到 DB_TRX_ID,表明:① 在当前事务创建快照前,该记录行的值被事务 ID 为 DB_TRX_ID 的事务修改了,但没有提交;或者 ② 在当前事务创建快照后,该记录行的值被事务 ID 为 DB_TRX_ID 的事务修改了。这些情况下,这个记录行的值对当前事务都是不可见的。跳到步骤 5 @@ -149,7 +171,7 @@ - 此时最新记录的 `DB_TRX_ID` 为 102,m_up_limit_id <= 102 < m_low_limit_id,所以要在 `m_ids` 列表中查找,发现 `DB_TRX_ID` 存在列表中,那么这个记录不可见 -- 根据 `DB_ROLL_PTR` 找到 `undo log` 中的上一版本记录,上一条记录的 `DB_TRX_ID` 为 101,满足 102 < m_up_limit_id,记录可见,所以在 `T6` 时间点查询到数据为 `name = 李四`,与时间 T4 查询到的结果不一致,不可重复读! +- 根据 `DB_ROLL_PTR` 找到 `undo log` 中的上一版本记录,上一条记录的 `DB_TRX_ID` 为 101,满足 101 < m_up_limit_id,记录可见,所以在 `T6` 时间点查询到数据为 `name = 李四`,与时间 T4 查询到的结果不一致,不可重复读! 3. **`时间线来到 T9 ,数据的版本链为`:** @@ -210,6 +232,6 @@ ## 参考 - **《MySQL 技术内幕 InnoDB 存储引擎第 2 版》** - - [Innodb 中的事务隔离级别和锁的关系](https://tech.meituan.com/2014/08/20/innodb-lock.html) -- [MySQL 事务与 MVCC 如何实现的隔离级别](https://blog.csdn.net/qq_35190492/article/details/109044141) \ No newline at end of file +- [MySQL 事务与 MVCC 如何实现的隔离级别](https://blog.csdn.net/qq_35190492/article/details/109044141) +- [InnoDB 事务分析-MVCC](https://leviathan.vip/2019/03/20/InnoDB%E7%9A%84%E4%BA%8B%E5%8A%A1%E5%88%86%E6%9E%90-MVCC/) diff --git a/docs/database/mysql/MySQL三大日志(binlog、redo log和undo log).md b/docs/database/mysql/MySQL三大日志.md similarity index 96% rename from docs/database/mysql/MySQL三大日志(binlog、redo log和undo log).md rename to docs/database/mysql/MySQL三大日志.md index 616fab71..ee621ba0 100644 --- a/docs/database/mysql/MySQL三大日志(binlog、redo log和undo log).md +++ b/docs/database/mysql/MySQL三大日志.md @@ -217,7 +217,7 @@ `binlog`(归档日志)保证了`MySQL`集群架构的数据一致性。 -虽然它们都属于持久化的保证,但是则重点不同。 +虽然它们都属于持久化的保证,但是侧重点不同。 在执行更新语句过程,会记录`redo log`与`binlog`两块日志,以基本的事务为单位,`redo log`在事务执行过程中可以不断写入,而`binlog`只有在提交事务时才写入,所以`redo log`与`binlog`的写入时机不一样。 @@ -255,7 +255,7 @@ > 这部分内容为 JavaGuide 的补充: -我们知道如果想要保证事务的原子性,就需要在异常发生时,对已经执行的操作进行**回滚**,在 MySQL 中,恢复机制是通过 **回滚日志(undo log)** 实现的,所有事务进行的修改都会先先记录到这个回滚日志中,然后再执行相关的操作。如果执行过程中遇到异常的话,我们直接利用 **回滚日志** 中的信息将数据回滚到修改之前的样子即可!并且,回滚日志会先于数据持久化到磁盘上。这样就保证了即使遇到数据库突然宕机等情况,当用户再次启动数据库的时候,数据库还能够通过查询回滚日志来回滚将之前未完成的事务。 +我们知道如果想要保证事务的原子性,就需要在异常发生时,对已经执行的操作进行**回滚**,在 MySQL 中,恢复机制是通过 **回滚日志(undo log)** 实现的,所有事务进行的修改都会先记录到这个回滚日志中,然后再执行相关的操作。如果执行过程中遇到异常的话,我们直接利用 **回滚日志** 中的信息将数据回滚到修改之前的样子即可!并且,回滚日志会先于数据持久化到磁盘上。这样就保证了即使遇到数据库突然宕机等情况,当用户再次启动数据库的时候,数据库还能够通过查询回滚日志来回滚将之前未完成的事务。 另外,`MVCC` 的实现依赖于:**隐藏字段、Read View、undo log**。在内部实现中,`InnoDB` 通过数据行的 `DB_TRX_ID` 和 `Read View` 来判断数据的可见性,如不可见,则通过数据行的 `DB_ROLL_PTR` 找到 `undo log` 中的历史版本。每个事务读到的数据版本可能是不一样的,在同一个事务中,用户只能看到该事务创建 `Read View` 之前已经提交的修改和该事务本身做的修改 @@ -277,4 +277,4 @@ MySQL InnoDB 引擎使用 **redo log(重做日志)** 保证事务的**持久性* ## 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 +- [浅谈 MySQL InnoDB 的内存组件](https://mp.weixin.qq.com/s/7Kab4IQsNcU_bZdbv_MuOg) diff --git a/docs/database/mysql/一千行MySQL学习笔记.md b/docs/database/mysql/一千行MySQL学习笔记.md index 385aa37d..bf8b5e58 100644 --- a/docs/database/mysql/一千行MySQL学习笔记.md +++ b/docs/database/mysql/一千行MySQL学习笔记.md @@ -609,7 +609,7 @@ CREATE [OR REPLACE] [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}] VIEW view_name - 事务开始和结束时,外部数据一致 - 在整个事务过程中,操作是连续的 3. 隔离性(Isolation) - 多个用户并发访问数据库时,一个用户的事务不能被其它用户的事物所干扰,多个并发事务之间的数据要相互隔离。 + 多个用户并发访问数据库时,一个用户的事务不能被其它用户的事务所干扰,多个并发事务之间的数据要相互隔离。 4. 持久性(Durability) 一个事务一旦被提交,它对数据库中的数据改变就是永久性的。 -- 事务的实现 diff --git a/docs/database/数据库基础知识.md b/docs/database/数据库基础知识.md index 71af7f01..92f16b97 100644 --- a/docs/database/数据库基础知识.md +++ b/docs/database/数据库基础知识.md @@ -3,7 +3,7 @@ ## 什么是数据库,数据库管理系统,数据库系统,数据库管理员? - **数据库** :数据库(DataBase 简称 DB)就是信息的集合或者说数据库是由数据库管理系统管理的数据的集合。 -- **数据库管理系统** : 数据库管理系统(Database Management System 简称 DBMS)是一种操纵和管理数据库的大型软件,通常用语用于建立、使用和维护数据库。 +- **数据库管理系统** : 数据库管理系统(Database Management System 简称 DBMS)是一种操纵和管理数据库的大型软件,通常用于建立、使用和维护数据库。 - **数据库系统** : 数据库系统(Data Base System,简称 DBS)通常由软件、数据库和数据管理员(DBA)组成。 - **数据库管理员** : 数据库管理员(Database Administrator,简称 DBA)负责全面管理和控制数据库系统。 @@ -28,7 +28,7 @@ ## 什么是 ER 图? -> 我们做一个项目的时候一定要试着花 ER 图来捋清数据库设计,这个也是面试官问你项目的时候经常会被问道的。 +> 我们做一个项目的时候一定要试着画 ER 图来捋清数据库设计,这个也是面试官问你项目的时候经常会被问道的。 **E-R 图**也称实体-联系图(Entity Relationship Diagram),提供了表示实体类型、属性和联系的方法,用来描述现实世界的概念模型。 它是描述现实世界关系概念模型的有效方法。 是表示概念关系模型的一种方式。 @@ -115,4 +115,4 @@ truncate 和 drop 属于 DDL(数据定义语言)语句,操作立即生效, - - -- \ No newline at end of file +- diff --git a/docs/java/basis/BIO,NIO,AIO总结.md b/docs/java/basis/BIO,NIO,AIO总结.md index 50f6b7fe..33a7ac50 100644 --- a/docs/java/basis/BIO,NIO,AIO总结.md +++ b/docs/java/basis/BIO,NIO,AIO总结.md @@ -34,10 +34,10 @@ > When you execute something synchronously, you wait for it to finish before moving on to another task. When you execute something asynchronously, you can move on to another task before it finishes. > -> 当你同步执行某项任务时,你需要等待其完成才能继续执行其他任务。当你异步执行某些操作时,你可以在完成另一个任务之前继续进行。 +> 当你同步执行某项任务时,你需要等待其完成才能继续执行其他任务。当您异步执行某项任务时,你可以在它完成之前继续执行其他任务。 - **同步** :两个同步任务相互依赖,并且一个任务必须以依赖于另一任务的某种方式执行。 比如在`A->B`事件模型中,你需要先完成 A 才能执行B。 再换句话说,同步调用中被调用者未处理完请求之前,调用不返回,调用者会一直等待结果的返回。 -- **异步**: 两个异步的任务是完全独立的,一方的执行不需要等待另外一方的执行。再换句话说,异步调用中一调用就返回结果不需要等待结果返回,当结果返回的时候通过回调函数或者其他方式拿着结果再做相关事情, +- **异步**: 两个异步的任务是完全独立的,一方的执行不需要等待另外一方的执行。再换句话说,异步调用中一调用就返回结果不需要等待结果返回,当结果返回的时候通过回调函数或者其他方式拿着结果再做相关事情。 **阻塞和非阻塞** @@ -58,7 +58,7 @@ BIO通信(一请求一应答)模型图如下(图源网络,原出处不明) ![传统BIO通信模型图](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2.png) -采用 **BIO 通信模型** 的服务端,通常由一个独立的 Acceptor 线程负责监听客户端的连接。我们一般通过在`while(true)` 循环中服务端会调用 `accept()` 方法等待接收客户端的连接的方式监听请求,请求一旦接收到一个连接请求,就可以建立通信套接字在这个通信套接字上进行读写操作,此时不能再接收其他客户端连接请求,只能等待同当前连接的客户端的操作执行完成, 不过可以通过多线程来支持多个客户端的连接,如上图所示。 +采用 **BIO 通信模型** 的服务端,通常由一个独立的 Acceptor 线程负责监听客户端的连接。我们一般通过在`while(true)` 循环中服务端会调用 `accept()` 方法等待接收客户端的连接的方式监听请求,一旦接收到一个连接请求,就可以建立通信套接字在这个通信套接字上进行读写操作,此时不能再接收其他客户端连接请求,只能等待同当前连接的客户端的操作执行完成, 不过可以通过多线程来支持多个客户端的连接,如上图所示。 如果要让 **BIO 通信模型** 能够同时处理多个客户端请求,就必须使用多线程(主要原因是`socket.accept()`、`socket.read()`、`socket.write()` 涉及的三个主要函数都是同步阻塞的),也就是说它在接收到客户端连接请求之后为每个客户端创建一个新的线程进行链路处理,处理完成之后,通过输出流返回应答给客户端,线程销毁。这就是典型的 **一请求一应答通信模型** 。我们可以设想一下如果这个连接不做任何事情的话就会造成不必要的线程开销,不过可以通过 **线程池机制** 改善,线程池还可以让线程的创建和回收成本相对较低。使用`FixedThreadPool` 可以有效的控制了线程的最大数量,保证了系统有限的资源的控制,实现了N(客户端请求数量):M(处理客户端请求的线程数量)的伪异步I/O模型(N 可以远远大于 M),下面一节"伪异步 BIO"中会详细介绍到。 @@ -193,7 +193,7 @@ Java IO的各种流是阻塞的。这意味着,当一个线程调用 `read()` Buffer是一个对象,它包含一些要写入或者要读出的数据。在NIO类库中加入Buffer对象,体现了新库与原I/O的一个重要区别。在面向流的I/O中·可以将数据直接写入或者将数据直接读到 Stream 对象中。虽然 Stream 中也有 Buffer 开头的扩展类,但只是流的包装类,还是从流读到缓冲区,而 NIO 却是直接读到 Buffer 中进行操作。 -在NIO厍中,所有数据都是用缓冲区处理的。在读取数据时,它是直接读到缓冲区中的; 在写入数据时,写入到缓冲区中。任何时候访问NIO中的数据,都是通过缓冲区进行操作。 +在NIO库中,所有数据都是用缓冲区处理的。在读取数据时,它是直接读到缓冲区中的; 在写入数据时,写入到缓冲区中。任何时候访问NIO中的数据,都是通过缓冲区进行操作。 最常用的缓冲区是 ByteBuffer,一个 ByteBuffer 提供了一组功能用于操作 byte 数组。除了ByteBuffer,还有其他的一些缓冲区,事实上,每一种Java基本类型(除了Boolean类型)都对应有一种缓冲区。 diff --git a/docs/java/basis/IO模型.md b/docs/java/basis/IO模型.md index 730e1e24..6091a8fe 100644 --- a/docs/java/basis/IO模型.md +++ b/docs/java/basis/IO模型.md @@ -18,7 +18,7 @@ I/O(**I**nput/**O**utpu) 即**输入/输出** 。 ![冯诺依曼体系结构](https://img-blog.csdnimg.cn/20190624122126398.jpeg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9pcy1jbG91ZC5ibG9nLmNzZG4ubmV0,size_16,color_FFFFFF,t_70) -输入设备(比如键盘)和输出设备(比如鼠标)都属于外部设备。网卡、硬盘这种既可以属于输入设备,也可以属于输出设备。 +输入设备(比如键盘)和输出设备(比如显示器)都属于外部设备。网卡、硬盘这种既可以属于输入设备,也可以属于输出设备。 输入设备向计算机输入数据,输出设备接收计算机输出的数据。 @@ -28,7 +28,7 @@ I/O(**I**nput/**O**utpu) 即**输入/输出** 。 根据大学里学到的操作系统相关的知识:为了保证操作系统的稳定性和安全性,一个进程的地址空间划分为 **用户空间(User space)** 和 **内核空间(Kernel space )** 。 -像我们平常运行的应用程序都是运行在用户空间,只有内核空间才能进行系统态级别的资源有关的操作,比如如文件管理、进程通信、内存管理等等。也就是说,我们想要进行 IO 操作,一定是要依赖内核空间的能力。 +像我们平常运行的应用程序都是运行在用户空间,只有内核空间才能进行系统态级别的资源有关的操作,比如文件管理、进程通信、内存管理等等。也就是说,我们想要进行 IO 操作,一定是要依赖内核空间的能力。 并且,用户空间的程序不能直接访问内核空间。 @@ -57,7 +57,7 @@ UNIX 系统下, IO 模型一共有 5 种: **同步阻塞 I/O**、**同步非 **BIO 属于同步阻塞 IO 模型** 。 -同步阻塞 IO 模型中,应用程序发起 read 调用后,会一直阻塞,直到在内核把数据拷贝到用户空间。 +同步阻塞 IO 模型中,应用程序发起 read 调用后,会一直阻塞,直到内核把数据拷贝到用户空间。 ![图源:《深入拆解Tomcat & Jetty》](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/6a9e704af49b4380bb686f0c96d33b81~tplv-k3u1fbpfcp-watermark.image) diff --git a/docs/java/basis/Java基础知识.md b/docs/java/basis/Java基础知识.md index 7c03a111..78e4e631 100644 --- a/docs/java/basis/Java基础知识.md +++ b/docs/java/basis/Java基础知识.md @@ -117,17 +117,17 @@ JRE 是 Java 运行时环境。它是运行已编译 Java 程序所需的所有 高级编程语言按照程序的执行方式分为编译型和解释型两种。简单来说,编译型语言是指编译器针对特定的操作系统将源代码一次性翻译成可被该平台执行的机器码;解释型语言是指解释器对源程序逐行解释成特定平台的机器码并立即执行。比如,你想阅读一本英文名著,你可以找一个英文翻译人员帮助你阅读, 有两种选择方式,你可以先等翻译人员将全本的英文名著(也就是源码)都翻译成汉语,再去阅读,也可以让翻译人员翻译一段,你在旁边阅读一段,慢慢把书读完。 -Java 语言既具有编译型语言的特征,也具有解释型语言的特征,因为 Java 程序要经过先编译,后解释两个步骤,由 Java 编写的程序需要先经过编译步骤,生成字节码(`\*.class` 文件),这种字节码必须由 Java 解释器来解释执行。因此,我们可以认为 Java 语言编译与解释并存。 +Java 语言既具有编译型语言的特征,也具有解释型语言的特征,因为 Java 程序要经过先编译,后解释两个步骤,由 Java 编写的程序需要先经过编译步骤,生成字节码(`*.class` 文件),这种字节码必须由 Java 解释器来解释执行。因此,我们可以认为 Java 语言编译与解释并存。 ### Oracle JDK 和 OpenJDK 的对比 -可能在看这个问题之前很多人和我一样并没有接触和使用过 OpenJDK 。那么 Oracle 和 OpenJDK 之间是否存在重大差异?下面我通过收集到的一些资料,为你解答这个被很多人忽视的问题。 +可能在看这个问题之前很多人和我一样并没有接触和使用过 OpenJDK 。那么 Oracle JDK 和 OpenJDK 之间是否存在重大差异?下面我通过收集到的一些资料,为你解答这个被很多人忽视的问题。 对于 Java 7,没什么关键的地方。OpenJDK 项目主要基于 Sun 捐赠的 HotSpot 源代码。此外,OpenJDK 被选为 Java 7 的参考实现,由 Oracle 工程师维护。关于 JVM,JDK,JRE 和 OpenJDK 之间的区别,Oracle 博客帖子在 2012 年有一个更详细的答案: > 问:OpenJDK 存储库中的源代码与用于构建 Oracle JDK 的代码之间有什么区别? > -> 答:非常接近 - 我们的 Oracle JDK 版本构建过程基于 OpenJDK 7 构建,只添加了几个部分,例如部署代码,其中包括 Oracle 的 Java 插件和 Java WebStart 的实现,以及一些封闭的源代码派对组件,如图形光栅化器,一些开源的第三方组件,如 Rhino,以及一些零碎的东西,如附加文档或第三方字体。展望未来,我们的目的是开源 Oracle JDK 的所有部分,除了我们考虑商业功能的部分。 +> 答:非常接近 - 我们的 Oracle JDK 版本构建过程基于 OpenJDK 7 构建,只添加了几个部分,例如部署代码,其中包括 Oracle 的 Java 插件和 Java WebStart 的实现,以及一些闭源的第三方组件,如图形光栅化器,一些开源的第三方组件,如 Rhino,以及一些零碎的东西,如附加文档或第三方字体。展望未来,我们的目的是开源 Oracle JDK 的所有部分,除了我们考虑商业功能的部分。 **总结:** @@ -216,8 +216,9 @@ Java 中的注释有三种: ### Java 中有哪些常见的关键字? +| 分类 | 关键字 | | | | | | | +| :-------------------- | -------- | ---------- | -------- | ------------ | ---------- | --------- | ------ | | 访问控制 | private | protected | public | | | | | -| -------------------- | -------- | ---------- | -------- | ------------ | ---------- | --------- | ------ | | 类,方法和变量修饰符 | abstract | class | extends | final | implements | interface | native | | | new | static | strictfp | synchronized | transient | volatile | | | 程序控制 | break | continue | return | do | while | if | else | @@ -456,7 +457,7 @@ public native int hashCode(); 在这里解释一位小伙伴的问题。以下内容摘自《Head Fisrt Java》。 -因为 `hashCode()` 所使用的哈希算法也许刚好会让多个对象传回相同的哈希值。越糟糕的哈希算法越容易碰撞,但这也与数据值域分布的特性有关(所谓碰撞也就是指的是不同的对象得到相同的 `hashCode`。 +因为 `hashCode()` 所使用的哈希算法也许刚好会让多个对象传回相同的哈希值。越糟糕的哈希算法越容易碰撞,但这也与数据值域分布的特性有关(所谓碰撞也就是指的是不同的对象得到相同的 `hashCode` )。 我们刚刚也提到了 `HashSet`,如果 `HashSet` 在对比的时候,同样的 hashcode 有多个对象,它会使用 `equals()` 来判断是否真的相同。也就是说 `hashcode` 只是用来缩小查找成本。 @@ -500,7 +501,7 @@ Java 中有 8 种基本数据类型,分别为: 基本数据类型直接存放在 Java 虚拟机栈中的局部变量表中,而包装类型属于对象类型,我们知道对象实例都存在于堆中。相比于对象类型, 基本数据类型占用的空间非常小。 -> 《深入理解 Java 虚拟机》 :局部变量表主要存放了编译期可知的基本数据类型**(boolean、byte、char、short、int、float、long、double)**、**对象引用**(reference 类型,它不同于对象本身,可能是一个指向对象起始地址的引用指针,也可能是指向一个代表对象的句柄或其他与此对象相关的位置)。 +> 《深入理解 Java 虚拟机》 :局部变量表主要存放了编译期可知的基本数据类型 **(boolean、byte、char、short、int、float、long、double)**、**对象引用**(reference 类型,它不同于对象本身,可能是一个指向对象起始地址的引用指针,也可能是指向一个代表对象的句柄或其他与此对象相关的位置)。 ### 自动装箱与拆箱 @@ -959,7 +960,7 @@ Java 程序设计语言对对象采用的不是引用调用,实际上,对象 - “两小”指的是子类方法返回值类型应比父类方法返回值类型更小或相等,子类方法声明抛出的异常类应比父类方法声明抛出的异常类更小或相等; - “一大”指的是子类方法的访问权限应比父类方法的访问权限更大或相等。 -⭐️ 关于 **重写的返回值类**型 这里需要额外多说明一下,上面的表述不太清晰准确:如果方法的返回类型是 void 和基本数据类型,则返回值重写时不可修改。但是如果方法的返回值是引用类型,重写时是可以返回该引用类型的子类的。 +⭐️ 关于 **重写的返回值类型** 这里需要额外多说明一下,上面的表述不太清晰准确:如果方法的返回类型是 void 和基本数据类型,则返回值重写时不可修改。但是如果方法的返回值是引用类型,重写时是可以返回该引用类型的子类的。 ```java public class Hero { @@ -1257,9 +1258,9 @@ Java 代码在编译过程中 ,我们即使不处理不受检查异常也可 ### Throwable 类常用方法 -- **`public string getMessage()`**:返回异常发生时的简要描述 -- **`public string toString()`**:返回异常发生时的详细信息 -- **`public string getLocalizedMessage()`**:返回异常对象的本地化信息。使用 `Throwable` 的子类覆盖这个方法,可以生成本地化信息。如果子类没有覆盖该方法,则该方法返回的信息与 `getMessage()`返回的结果相同 +- **`public String getMessage()`**:返回异常发生时的简要描述 +- **`public String toString()`**:返回异常发生时的详细信息 +- **`public String getLocalizedMessage()`**:返回异常对象的本地化信息。使用 `Throwable` 的子类覆盖这个方法,可以生成本地化信息。如果子类没有覆盖该方法,则该方法返回的信息与 `getMessage()`返回的结果相同 - **`public void printStackTrace()`**:在控制台上打印 `Throwable` 对象封装的异常信息 ### try-catch-finally @@ -1270,9 +1271,9 @@ Java 代码在编译过程中 ,我们即使不处理不受检查异常也可 **在以下 3 种特殊情况下,`finally` 块不会被执行:** -2. 在 `try` 或 `finally`块中用了 `System.exit(int)`退出程序。但是,如果 `System.exit(int)` 在异常语句之后,`finally` 还是会被执行 -3. 程序所在的线程死亡。 -4. 关闭 CPU。 +1. 在 `try` 或 `finally`块中用了 `System.exit(int)`退出程序。但是,如果 `System.exit(int)` 在异常语句之后,`finally` 还是会被执行 +2. 程序所在的线程死亡。 +3. 关闭 CPU。 下面这部分内容来自 issue:。 @@ -1360,7 +1361,7 @@ try (BufferedInputStream bin = new BufferedInputStream(new FileInputStream(new F 简单来说: - **序列化**: 将数据结构或对象转换成二进制字节流的过程 -- **反序列化**:将在序列化过程中所生成的二进制字节流的过程转换成数据结构或者对象的过程 +- **反序列化**:将在序列化过程中所生成的二进制字节流转换成数据结构或者对象的过程 对于 Java 这种面向对象编程语言来说,我们序列化的都是对象(Object)也就是实例化后的类(Class),但是在 C++这种半面向对象的语言中,struct(结构体)定义的是数据结构类型,而 class 对应的是对象类型。 @@ -1408,7 +1409,7 @@ String s = input.readLine(); - 按照操作单元划分,可以划分为字节流和字符流; - 按照流的角色划分为节点流和处理流。 -Java Io 流共涉及 40 多个类,这些类看上去很杂乱,但实际上很有规则,而且彼此之间存在非常紧密的联系, Java I0 流的 40 多个类都是从如下 4 个抽象类基类中派生出来的。 +Java IO 流共涉及 40 多个类,这些类看上去很杂乱,但实际上很有规则,而且彼此之间存在非常紧密的联系, Java IO 流的 40 多个类都是从如下 4 个抽象类基类中派生出来的。 - InputStream/Reader: 所有的输入流的基类,前者是字节输入流,后者是字符输入流。 - OutputStream/Writer: 所有输出流的基类,前者是字节输出流,后者是字符输出流。 diff --git a/docs/java/basis/Java基础知识疑难点.md b/docs/java/basis/Java基础知识疑难点.md index eb5c17b2..a1d414d4 100644 --- a/docs/java/basis/Java基础知识疑难点.md +++ b/docs/java/basis/Java基础知识疑难点.md @@ -1,29 +1,4 @@ - - -- [1. 基础](#1-基础) - - [1.1. 正确使用 equals 方法](#11-正确使用-equals-方法) - - [1.2. 整型包装类值的比较](#12-整型包装类值的比较) - - [1.3. BigDecimal](#13-bigdecimal) - - [1.3.1. BigDecimal 的用处](#131-bigdecimal-的用处) - - [1.3.2. BigDecimal 的大小比较](#132-bigdecimal-的大小比较) - - [1.3.3. BigDecimal 保留几位小数](#133-bigdecimal-保留几位小数) - - [1.3.4. BigDecimal 的使用注意事项](#134-bigdecimal-的使用注意事项) - - [1.3.5. 总结](#135-总结) - - [1.4. 基本数据类型与包装数据类型的使用标准](#14-基本数据类型与包装数据类型的使用标准) -- [2. 集合](#_2-集合) - - [2.1. Arrays.asList()使用指南](#21-arraysaslist使用指南) - - [2.1.1. 简介](#211-简介) - - [2.1.2. 《阿里巴巴Java 开发手册》对其的描述](#212-阿里巴巴java-开发手册对其的描述) - - [2.1.3. 使用时的注意事项总结](#213-使用时的注意事项总结) - - [2.1.4. 如何正确的将数组转换为ArrayList?](#214-如何正确的将数组转换为arraylist) - - [2.2. Collection.toArray()方法使用的坑&如何反转数组](#22-collectiontoarray方法使用的坑如何反转数组) - - [2.3. 不要在 foreach 循环里进行元素的 remove/add 操作](#23-不要在-foreach-循环里进行元素的-removeadd-操作) - - - -# 1. 基础 - -## 1.1. 正确使用 equals 方法 +## 正确使用 equals 方法 Object的equals方法容易抛空指针异常,应使用常量或确定有值的对象来调用 equals。 @@ -52,7 +27,7 @@ Objects.equals(null,"SnailClimb");// false 我们看一下`java.util.Objects#equals`的源码就知道原因了。 ```java public static boolean equals(Object a, Object b) { - // 可以避免空指针异常。如果a==null的话此时a.equals(b)就不会得到执行,避免出现空指针异常。 + // 可以避免空指针异常。如果a=null的话此时a.equals(b)就不会得到执行,避免出现空指针异常。 return (a == b) || (a != null && a.equals(b)); } ``` @@ -65,7 +40,7 @@ Reference:[Java中equals方法造成空指针异常的原因及解决方案](htt - 可以使用 == 或者 != 操作来比较null值,但是不能使用其他算法或者逻辑操作。在Java中`null == null`将返回true。 - 不能使用一个值为null的引用类型变量来调用非静态方法,否则会抛出异常 -## 1.2. 整型包装类值的比较 +## 整型包装类值的比较 所有整型包装类对象值的比较必须使用equals方法。 @@ -85,9 +60,9 @@ System.out.println(i1==i2);//false **注意:** 如果你的IDE(IDEA/Eclipse)上安装了阿里巴巴的p3c插件,这个插件如果检测到你用 ==的话会报错提示,推荐安装一个这个插件,很不错。 -## 1.3. BigDecimal +## BigDecimal -### 1.3.1. BigDecimal 的用处 +### BigDecimal 的用处 《阿里巴巴Java开发手册》中提到:**浮点数之间的等值判断,基本数据类型不能用==来比较,包装数据类型不能用 equals 来判断。** 具体原理和浮点数的编码方式有关,这里就不多提了,我们下面直接上实例: @@ -113,7 +88,7 @@ System.out.println(y); /* 0.1 */ System.out.println(Objects.equals(x, y)); /* true */ ``` -### 1.3.2. BigDecimal 的大小比较 +### BigDecimal 的大小比较 `a.compareTo(b)` : 返回 -1 表示 `a` 小于 `b`,0 表示 `a` 等于 `b` , 1表示 `a` 大于 `b`。 @@ -122,7 +97,7 @@ BigDecimal a = new BigDecimal("1.0"); BigDecimal b = new BigDecimal("0.9"); System.out.println(a.compareTo(b));// 1 ``` -### 1.3.3. BigDecimal 保留几位小数 +### BigDecimal 保留几位小数 通过 `setScale`方法设置保留几位小数以及保留规则。保留规则有挺多种,不需要记,IDEA会提示。 @@ -132,19 +107,19 @@ BigDecimal n = m.setScale(3,BigDecimal.ROUND_HALF_DOWN); System.out.println(n);// 1.255 ``` -### 1.3.4. BigDecimal 的使用注意事项 +### BigDecimal 的使用注意事项 注意:我们在使用BigDecimal时,为了防止精度丢失,推荐使用它的 **BigDecimal(String)** 构造方法来创建对象。《阿里巴巴Java开发手册》对这部分内容也有提到如下图所示。 ![《阿里巴巴Java开发手册》对这部分BigDecimal的描述](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019/7/BigDecimal.png) -### 1.3.5. 总结 +### 总结 BigDecimal 主要用来操作(大)浮点数,BigInteger 主要用来操作大整数(超过 long 类型)。 BigDecimal 的实现利用到了 BigInteger, 所不同的是 BigDecimal 加入了小数位的概念 -## 1.4. 基本数据类型与包装数据类型的使用标准 +## 基本数据类型与包装数据类型的使用标准 Reference:《阿里巴巴Java开发手册》 @@ -160,237 +135,3 @@ Reference:《阿里巴巴Java开发手册》 **反例** : 比如显示成交总额涨跌情况,即正负 x%,x 为基本数据类型,调用的 RPC 服务,调用不成功时,返回的是默认值,页面显示为 0%,这是不合理的,应该显示成中划线。所以包装数据类型的 null 值,能够表示额外的信息,如:远程调用失败,异常退出。 -# 2. 集合 - -## 2.1. Arrays.asList()使用指南 - -最近使用`Arrays.asList()`遇到了一些坑,然后在网上看到这篇文章:[Java Array to List Examples](http://javadevnotes.com/java-array-to-list-examples) 感觉挺不错的,但是还不是特别全面。所以,自己对于这块小知识点进行了简单的总结。 - -### 2.1.1. 简介 - -`Arrays.asList()`在平时开发中还是比较常见的,我们可以使用它将一个数组转换为一个List集合。 - -```java -String[] myArray = {"Apple", "Banana", "Orange"}; -List myList = Arrays.asList(myArray); -//上面两个语句等价于下面一条语句 -List myList = Arrays.asList("Apple","Banana", "Orange"); -``` - -JDK 源码对于这个方法的说明: - -```java -/** - *返回由指定数组支持的固定大小的列表。此方法作为基于数组和基于集合的API之间的桥梁, - * 与 Collection.toArray()结合使用。返回的List是可序列化并实现RandomAccess接口。 - */ -public static List asList(T... a) { - return new ArrayList<>(a); -} -``` - -### 2.1.2. 《阿里巴巴Java 开发手册》对其的描述 - -`Arrays.asList()`将数组转换为集合后,底层其实还是数组,《阿里巴巴Java 开发手册》对于这个方法有如下描述: - -![阿里巴巴Java开发手-Arrays.asList()方法](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-6/阿里巴巴Java开发手-Arrays.asList()方法.png) - -### 2.1.3. 使用时的注意事项总结 - -**传递的数组必须是对象数组,而不是基本类型。** - -`Arrays.asList()`是泛型方法,传入的对象必须是对象数组。 - -```java -int[] myArray = {1, 2, 3}; -List myList = Arrays.asList(myArray); -System.out.println(myList.size());//1 -System.out.println(myList.get(0));//数组地址值 -System.out.println(myList.get(1));//报错:ArrayIndexOutOfBoundsException -int[] array = (int[]) myList.get(0); -System.out.println(array[0]);//1 -``` -当传入一个原生数据类型数组时,`Arrays.asList()` 的真正得到的参数就不是数组中的元素,而是数组对象本身!此时List 的唯一元素就是这个数组,这也就解释了上面的代码。 - -我们使用包装类型数组就可以解决这个问题。 - -```java -Integer[] myArray = {1, 2, 3}; -``` - -**使用集合的修改方法:`add()`、`remove()`、`clear()`会抛出异常。** - -```java -List myList = Arrays.asList(1, 2, 3); -myList.add(4);//运行时报错:UnsupportedOperationException -myList.remove(1);//运行时报错:UnsupportedOperationException -myList.clear();//运行时报错:UnsupportedOperationException -``` - -`Arrays.asList()` 方法返回的并不是 `java.util.ArrayList` ,而是 `java.util.Arrays` 的一个内部类,这个内部类并没有实现集合的修改方法或者说并没有重写这些方法。 - -```java -List myList = Arrays.asList(1, 2, 3); -System.out.println(myList.getClass());//class java.util.Arrays$ArrayList -``` - -下图是`java.util.Arrays$ArrayList`的简易源码,我们可以看到这个类重写的方法有哪些。 - -```java - private static class ArrayList extends AbstractList - implements RandomAccess, java.io.Serializable - { - ... - - @Override - public E get(int index) { - ... - } - - @Override - public E set(int index, E element) { - ... - } - - @Override - public int indexOf(Object o) { - ... - } - - @Override - public boolean contains(Object o) { - ... - } - - @Override - public void forEach(Consumer action) { - ... - } - - @Override - public void replaceAll(UnaryOperator operator) { - ... - } - - @Override - public void sort(Comparator c) { - ... - } - } -``` - -我们再看一下`java.util.AbstractList`的`remove()`方法,这样我们就明白为啥会抛出`UnsupportedOperationException`。 - -```java -public E remove(int index) { - throw new UnsupportedOperationException(); -} -``` - -### 2.1.4. 如何正确的将数组转换为ArrayList? - -stackoverflow:https://dwz.cn/vcBkTiTW - -**1. 自己动手实现(教育目的)** - -```java -//JDK1.5+ -static List arrayToList(final T[] array) { - final List l = new ArrayList(array.length); - - for (final T s : array) { - l.add(s); - } - return l; -} -``` - -```java -Integer [] myArray = { 1, 2, 3 }; -System.out.println(arrayToList(myArray).getClass());//class java.util.ArrayList -``` - -**2. 最简便的方法(推荐)** - -```java -List list = new ArrayList<>(Arrays.asList("a", "b", "c")) -``` - -**3. 使用 Java8 的Stream(推荐)** - -```java -Integer [] myArray = { 1, 2, 3 }; -List myList = Arrays.stream(myArray).collect(Collectors.toList()); -//基本类型也可以实现转换(依赖boxed的装箱操作) -int [] myArray2 = { 1, 2, 3 }; -List myList = Arrays.stream(myArray2).boxed().collect(Collectors.toList()); -``` - -**4. 使用 Guava(推荐)** - -对于不可变集合,你可以使用[`ImmutableList`](https://github.com/google/guava/blob/master/guava/src/com/google/common/collect/ImmutableList.java)类及其[`of()`](https://github.com/google/guava/blob/master/guava/src/com/google/common/collect/ImmutableList.java#L101)与[`copyOf()`](https://github.com/google/guava/blob/master/guava/src/com/google/common/collect/ImmutableList.java#L225)工厂方法:(参数不能为空) - -```java -List il = ImmutableList.of("string", "elements"); // from varargs -List il = ImmutableList.copyOf(aStringArray); // from array -``` -对于可变集合,你可以使用[`Lists`](https://github.com/google/guava/blob/master/guava/src/com/google/common/collect/Lists.java)类及其[`newArrayList()`](https://github.com/google/guava/blob/master/guava/src/com/google/common/collect/Lists.java#L87)工厂方法: - -```java -List l1 = Lists.newArrayList(anotherListOrCollection); // from collection -List l2 = Lists.newArrayList(aStringArray); // from array -List l3 = Lists.newArrayList("or", "string", "elements"); // from varargs -``` - -**5. 使用 Apache Commons Collections** - -```java -List list = new ArrayList(); -CollectionUtils.addAll(list, str); -``` - -**6. 使用 Java9 的 `List.of()`方法** -``` java -Integer[] array = {1, 2, 3}; -List list = List.of(array); -System.out.println(list); /* [1, 2, 3] */ -/* 不支持基本数据类型 */ -``` - -## 2.2. Collection.toArray()方法使用的坑&如何反转数组 - -该方法是一个泛型方法:` T[] toArray(T[] a);` 如果`toArray`方法中没有传递任何参数的话返回的是`Object`类型数组。 - -```java -String [] s= new String[]{ - "dog", "lazy", "a", "over", "jumps", "fox", "brown", "quick", "A" -}; -List list = Arrays.asList(s); -Collections.reverse(list); -s=list.toArray(new String[0]);//没有指定类型的话会报错 -``` - -由于JVM优化,`new String[0]`作为`Collection.toArray()`方法的参数现在使用更好,`new String[0]`就是起一个模板的作用,指定了返回数组的类型,0是为了节省空间,因为它只是为了说明返回的类型。详见: - -## 2.3. 不要在 foreach 循环里进行元素的 remove/add 操作 - -如果要进行`remove`操作,可以调用迭代器的 `remove `方法而不是集合类的 remove 方法。因为如果列表在任何时间从结构上修改创建迭代器之后,以任何方式除非通过迭代器自身`remove/add`方法,迭代器都将抛出一个`ConcurrentModificationException`,这就是单线程状态下产生的 **fail-fast 机制**。 - -> **fail-fast 机制** :多个线程对 fail-fast 集合进行修改的时候,可能会抛出ConcurrentModificationException,单线程下也会出现这种情况,上面已经提到过。 - -Java8开始,可以使用`Collection#removeIf()`方法删除满足特定条件的元素,如 -``` java -List list = new ArrayList<>(); -for (int i = 1; i <= 10; ++i) { - list.add(i); -} -list.removeIf(filter -> filter % 2 == 0); /* 删除list中的所有偶数 */ -System.out.println(list); /* [1, 3, 5, 7, 9] */ -``` - -`java.util`包下面的所有的集合类都是fail-fast的,而`java.util.concurrent`包下面的所有的类都是fail-safe的。 - -![不要在 foreach 循环里进行元素的 remove/add 操作](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019/7/foreach-remove:add.png) - - - diff --git a/docs/java/basis/代理模式详解.md b/docs/java/basis/代理模式详解.md index 868bc012..8106d305 100644 --- a/docs/java/basis/代理模式详解.md +++ b/docs/java/basis/代理模式详解.md @@ -120,15 +120,15 @@ after method send() **从 JVM 角度来说,动态代理是在运行时动态生成类字节码,并加载到 JVM 中的。** -说到动态代理,Spring AOP、RPC 框架应该是两个不得不的提的,它们的实现都依赖了动态代理。 +说到动态代理,Spring AOP、RPC 框架应该是两个不得不提的,它们的实现都依赖了动态代理。 -**动态代理在我们日常开发中使用的相对较小,但是在框架中的几乎是必用的一门技术。学会了动态代理之后,对于我们理解和学习各种框架的原理也非常有帮助。** +**动态代理在我们日常开发中使用的相对较少,但是在框架中的几乎是必用的一门技术。学会了动态代理之后,对于我们理解和学习各种框架的原理也非常有帮助。** 就 Java 来说,动态代理的实现方式有很多种,比如 **JDK 动态代理**、**CGLIB 动态代理**等等。 [guide-rpc-framework](https://github.com/Snailclimb/guide-rpc-framework) 使用的是 JDK 动态代理,我们先来看看 JDK 动态代理的使用。 -另外,虽然 [guide-rpc-framework](https://github.com/Snailclimb/guide-rpc-framework) 没有用到 **CGLIB 动态代理 ,我们这里还是简单介绍一下其使用以及和**JDK 动态代理的对比。 +另外,虽然 [guide-rpc-framework](https://github.com/Snailclimb/guide-rpc-framework) 没有用到 **CGLIB 动态代理** ,我们这里还是简单介绍一下其使用以及和**JDK 动态代理**的对比。 ### 3.1. JDK 动态代理机制 @@ -154,7 +154,7 @@ after method send() 2. **interfaces** : 被代理类实现的一些接口; 3. **h** : 实现了 `InvocationHandler` 接口的对象; -要实现动态代理的话,还必须需要实现`InvocationHandler` 来自定义处理逻辑。 当我们的动态代理对象调用一个方法时候,这个方法的调用就会被转发到实现`InvocationHandler` 接口类的 `invoke` 方法来调用。 +要实现动态代理的话,还必须需要实现`InvocationHandler` 来自定义处理逻辑。 当我们的动态代理对象调用一个方法时,这个方法的调用就会被转发到实现`InvocationHandler` 接口类的 `invoke` 方法来调用。 ```java public interface InvocationHandler { @@ -298,7 +298,7 @@ extends Callback{ 1. **obj** :被代理的对象(需要增强的对象) 2. **method** :被拦截的方法(需要增强的方法) 3. **args** :方法入参 -4. **methodProxy** :用于调用原始方法 +4. **proxy** :用于调用原始方法 你可以通过 `Enhancer`类来动态获取被代理类,当代理类调用方法的时候,实际调用的是 `MethodInterceptor` 中的 `intercept` 方法。 diff --git a/docs/java/basis/用好Java中的枚举真的没有那么简单.md b/docs/java/basis/用好Java中的枚举真的没有那么简单.md index 23e47ef6..c17fcba9 100644 --- a/docs/java/basis/用好Java中的枚举真的没有那么简单.md +++ b/docs/java/basis/用好Java中的枚举真的没有那么简单.md @@ -12,7 +12,7 @@ enum关键字在 java5 中引入,表示一种特殊类型的类,其总是继承java.lang.Enum类,更多内容可以自行查看其[官方文档](https://docs.oracle.com/javase/6/docs/api/java/lang/Enum.html)。 -枚举在很多时候会和常量拿来对比,可能因为本身我们大量实际使用枚举的地方就是为了替代常量。那么这种方式由什么优势呢? +枚举在很多时候会和常量拿来对比,可能因为本身我们大量实际使用枚举的地方就是为了替代常量。那么这种方式有什么优势呢? **以这种方式定义的常量使代码更具可读性,允许进行编译时检查,预先记录可接受值的列表,并避免由于传入无效值而引起的意外行为。** @@ -219,7 +219,7 @@ public class Pizza { } ``` - 下面的测试演示了展示了 `EnumSet` 在某些场景下的强大功能: + 下面的测试展示了 `EnumSet` 在某些场景下的强大功能: ```java @Test @@ -272,7 +272,7 @@ while (iterator.hasNext()) { } ``` - 下面的测试演示了展示了 `EnumMap` 在某些场景下的强大功能: + 下面的测试展示了 `EnumMap` 在某些场景下的强大功能: ```java @Test @@ -308,7 +308,7 @@ public void givenPizaOrders_whenGroupByStatusCalled_thenCorrectlyGrouped() { 通常,使用类实现 Singleton 模式并非易事,枚举提供了一种实现单例的简便方法。 -《Effective Java 》和《Java与模式》都非常推荐这种方式,使用这种方式方式实现枚举可以有什么好处呢? +《Effective Java 》和《Java与模式》都非常推荐这种方式,使用这种方式实现枚举可以有什么好处呢? 《Effective Java》 @@ -401,9 +401,9 @@ public void givenPizaOrder_whenDelivered_thenPizzaGetsDeliveredAndStatusChanges( ## 8. Java 8 与枚举 -Pizza 类可以用Java 8重写,您可以看到方法 lambda 和Stream API如何使 `getAllUndeliveredPizzas()`和`groupPizzaByStatus()`方法变得如此简洁: +Pizza 类可以用Java 8重写,您可以看到方法 lambda 和Stream API如何使 `getAllUndeliveredPizzas()`和`groupPizzaByStatus()`方法变得如此简洁: -`getAllUndeliveredPizzas()`: +`getAllUndeliveredPizzas()`: ```java public static List getAllUndeliveredPizzas(List input) { @@ -413,7 +413,7 @@ public static List getAllUndeliveredPizzas(List input) { } ``` -`groupPizzaByStatus()` : +`groupPizzaByStatus()` : ```java public static EnumMap> @@ -554,4 +554,4 @@ Output: PinType{code=100001, message='忘记密码使用'} ``` -这样的话,在实际使用起来就会非常灵活方便! \ No newline at end of file +这样的话,在实际使用起来就会非常灵活方便! diff --git a/docs/java/collection/Java集合使用注意事项总结.md b/docs/java/collection/Java集合使用注意事项总结.md new file mode 100644 index 00000000..3c04c7af --- /dev/null +++ b/docs/java/collection/Java集合使用注意事项总结.md @@ -0,0 +1,432 @@ +这篇文章我根据《阿里巴巴 Java 开发手册》总结了关于集合使用常见的注意事项以及其具体原理。 + +强烈建议小伙伴们多多阅读几遍,避免自己写代码的时候出现这些低级的问题。 + +## 集合判空 + +《阿里巴巴 Java 开发手册》的描述如下: + +> **判断所有集合内部的元素是否为空,使用 `isEmpty()` 方法,而不是 `size()==0` 的方式。** + +这是因为 `isEmpty()` 方法的可读性更好,并且时间复杂度为 O(1)。 + +绝大部分我们使用的集合的 `size()` 方法的时间复杂度也是 O(1),不过,也有很多复杂度不是 O(1) 的,比如 `java.util.concurrent` 包下的某些集合(`ConcurrentLinkedQueue` 、`ConcurrentHashMap`...)。 + +下面是 `ConcurrentHashMap` 的 `size()` 方法和 `isEmpty()` 方法的源码。 + +```java +public int size() { + long n = sumCount(); + return ((n < 0L) ? 0 : + (n > (long)Integer.MAX_VALUE) ? Integer.MAX_VALUE : + (int)n); +} +final long sumCount() { + CounterCell[] as = counterCells; CounterCell a; + long sum = baseCount; + if (as != null) { + for (int i = 0; i < as.length; ++i) { + if ((a = as[i]) != null) + sum += a.value; + } + } + return sum; +} +public boolean isEmpty() { + return sumCount() <= 0L; // ignore transient negative values +} +``` + +## 集合转 Map + +《阿里巴巴 Java 开发手册》的描述如下: + +> **在使用 `java.util.stream.Collectors` 类的 `toMap()` 方法转为 `Map` 集合时,一定要注意当 value 为 null 时会抛 NPE 异常。** + +```java +class Person { + private String name; + private String phoneNumber; + // getters and setters +} + +List bookList = new ArrayList<>(); +bookList.add(new Person("jack","18163138123")); +bookList.add(new Person("martin",null)); +// 空指针异常 +bookList.stream().collect(Collectors.toMap(Person::getName, Person::getPhoneNumber)); +``` + +下面我们来解释一下原因。 + +首先,我们来看 `java.util.stream.Collectors` 类的 `toMap()` 方法 ,可以看到其内部调用了 `Map` 接口的 `merge()` 方法。 + +```java +public static > +Collector toMap(Function keyMapper, + Function valueMapper, + BinaryOperator mergeFunction, + Supplier mapSupplier) { + BiConsumer accumulator + = (map, element) -> map.merge(keyMapper.apply(element), + valueMapper.apply(element), mergeFunction); + return new CollectorImpl<>(mapSupplier, accumulator, mapMerger(mergeFunction), CH_ID); +} +``` + +`Map` 接口的 `merge()` 方法如下,这个方法是接口中的默认实现。 + +> 如果你还不了解 Java 8 新特性的话,请看这篇文章:[《Java8 新特性总结》](https://mp.weixin.qq.com/s/ojyl7B6PiHaTWADqmUq2rw) 。 + +```java +default V merge(K key, V value, + BiFunction remappingFunction) { + Objects.requireNonNull(remappingFunction); + Objects.requireNonNull(value); + V oldValue = get(key); + V newValue = (oldValue == null) ? value : + remappingFunction.apply(oldValue, value); + if(newValue == null) { + remove(key); + } else { + put(key, newValue); + } + return newValue; +} +``` + +`merge()` 方法会先调用 `Objects.requireNonNull()` 方法判断 value 是否为空。 + +```java +public static T requireNonNull(T obj) { + if (obj == null) + throw new NullPointerException(); + return obj; +} +``` + +## 集合遍历 + +《阿里巴巴 Java 开发手册》的描述如下: + +> **不要在 foreach 循环里进行元素的 `remove/add` 操作。remove 元素请使用 `Iterator` 方式,如果并发操作,需要对 `Iterator` 对象加锁。** + +通过反编译你会发现 foreach 语法糖底层其实还是依赖 `Iterator` 。不过, `remove/add` 操作直接调用的是集合自己的方法,而不是 `Iterator` 的 `remove/add`方法 + +这就导致 `Iterator` 莫名其妙地发现自己有元素被 `remove/add` ,然后,它就会抛出一个 `ConcurrentModificationException` 来提示用户发生了并发修改异常。这就是单线程状态下产生的 **fail-fast 机制**。 + +> **fail-fast 机制** :多个线程对 fail-fast 集合进行修改的时候,可能会抛出`ConcurrentModificationException`。 即使是单线程下也有可能会出现这种情况,上面已经提到过。 + +Java8 开始,可以使用 `Collection#removeIf()`方法删除满足特定条件的元素,如 + +```java +List list = new ArrayList<>(); +for (int i = 1; i <= 10; ++i) { + list.add(i); +} +list.removeIf(filter -> filter % 2 == 0); /* 删除list中的所有偶数 */ +System.out.println(list); /* [1, 3, 5, 7, 9] */ +``` + +除了上面介绍的直接使用 `Iterator` 进行遍历操作之外,你还可以: + +- 使用普通的 for 循环 +- 使用 fail-safe 的集合类。`java.util`包下面的所有的集合类都是 fail-fast 的,而`java.util.concurrent`包下面的所有的类都是 fail-safe 的。 +- ...... + +## 集合去重 + +《阿里巴巴 Java 开发手册》的描述如下: + +> **可以利用 `Set` 元素唯一的特性,可以快速对一个集合进行去重操作,避免使用 `List` 的 `contains()` 进行遍历去重或者判断包含操作。** + +这里我们以 `HashSet` 和 `ArrayList` 为例说明。 + +```java +// Set 去重代码示例 +public static Set removeDuplicateBySet(List data) { + + if (CollectionUtils.isEmpty(data)) { + return new HashSet<>(); + } + return new HashSet<>(data); +} + +// List 去重代码示例 +public static List removeDuplicateByList(List data) { + + if (CollectionUtils.isEmpty(data)) { + return new ArrayList<>(); + + } + List result = new ArrayList<>(data.size()); + for (T current : data) { + if (!result.contains(current)) { + result.add(current); + } + } + return result; +} + +``` + +两者的核心差别在于 `contains()` 方法的实现。 + +`HashSet` 的 `contains()` 方法底部依赖的 `HashMap` 的 `containsKey()` 方法,时间复杂度接近于 O(1)(没有出现哈希冲突的时候为 O(1))。 + +```java +private transient HashMap map; +public boolean contains(Object o) { + return map.containsKey(o); +} +``` + +我们有 N 个元素插入进 Set 中,那时间复杂度就接近是 O (n)。 + +`ArrayList` 的 `contains()` 方法是通过遍历所有元素的方法来做的,时间复杂度接近是 O(n)。 + +```java +public boolean contains(Object o) { + return indexOf(o) >= 0; +} +public int indexOf(Object o) { + if (o == null) { + for (int i = 0; i < size; i++) + if (elementData[i]==null) + return i; + } else { + for (int i = 0; i < size; i++) + if (o.equals(elementData[i])) + return i; + } + return -1; +} + +``` + +我们的 `List` 有 N 个元素,那时间复杂度就接近是 O (n^2)。 + +## 集合转数组 + +《阿里巴巴 Java 开发手册》的描述如下: + +> **使用集合转数组的方法,必须使用集合的 `toArray(T[] array)`,传入的是类型完全一致、长度为 0 的空数组。** + +`toArray(T[] array)` 方法的参数是一个泛型数组,如果 `toArray` 方法中没有传递任何参数的话返回的是 `Object`类 型数组。 + +```java +String [] s= new String[]{ + "dog", "lazy", "a", "over", "jumps", "fox", "brown", "quick", "A" +}; +List list = Arrays.asList(s); +Collections.reverse(list); +//没有指定类型的话会报错 +s=list.toArray(new String[0]); +``` + +由于 JVM 优化,`new String[0]`作为`Collection.toArray()`方法的参数现在使用更好,`new String[0]`就是起一个模板的作用,指定了返回数组的类型,0 是为了节省空间,因为它只是为了说明返回的类型。详见: + +## 数组转集合 + +《阿里巴巴 Java 开发手册》的描述如下: + +> **使用工具类 `Arrays.asList()` 把数组转换成集合时,不能使用其修改集合相关的方法, 它的 `add/remove/clear` 方法会抛出 `UnsupportedOperationException` 异常。** + +我在之前的一个项目中就遇到一个类似的坑。 + +`Arrays.asList()`在平时开发中还是比较常见的,我们可以使用它将一个数组转换为一个 `List` 集合。 + +```java +String[] myArray = {"Apple", "Banana", "Orange"}; +List myList = Arrays.asList(myArray); +//上面两个语句等价于下面一条语句 +List myList = Arrays.asList("Apple","Banana", "Orange"); +``` + +JDK 源码对于这个方法的说明: + +```java +/** + *返回由指定数组支持的固定大小的列表。此方法作为基于数组和基于集合的API之间的桥梁, + * 与 Collection.toArray()结合使用。返回的List是可序列化并实现RandomAccess接口。 + */ +public static List asList(T... a) { + return new ArrayList<>(a); +} +``` + +下面我们来总结一下使用注意事项。 + +**1、`Arrays.asList()`是泛型方法,传递的数组必须是对象数组,而不是基本类型。** + +```java +int[] myArray = {1, 2, 3}; +List myList = Arrays.asList(myArray); +System.out.println(myList.size());//1 +System.out.println(myList.get(0));//数组地址值 +System.out.println(myList.get(1));//报错:ArrayIndexOutOfBoundsException +int[] array = (int[]) myList.get(0); +System.out.println(array[0]);//1 +``` + +当传入一个原生数据类型数组时,`Arrays.asList()` 的真正得到的参数就不是数组中的元素,而是数组对象本身!此时 `List` 的唯一元素就是这个数组,这也就解释了上面的代码。 + +我们使用包装类型数组就可以解决这个问题。 + +```java +Integer[] myArray = {1, 2, 3}; +``` + +**2、使用集合的修改方法: `add()`、`remove()`、`clear()`会抛出异常。** + +```java +List myList = Arrays.asList(1, 2, 3); +myList.add(4);//运行时报错:UnsupportedOperationException +myList.remove(1);//运行时报错:UnsupportedOperationException +myList.clear();//运行时报错:UnsupportedOperationException +``` + +`Arrays.asList()` 方法返回的并不是 `java.util.ArrayList` ,而是 `java.util.Arrays` 的一个内部类,这个内部类并没有实现集合的修改方法或者说并没有重写这些方法。 + +```java +List myList = Arrays.asList(1, 2, 3); +System.out.println(myList.getClass());//class java.util.Arrays$ArrayList +``` + +下图是 `java.util.Arrays$ArrayList` 的简易源码,我们可以看到这个类重写的方法有哪些。 + +```java + private static class ArrayList extends AbstractList + implements RandomAccess, java.io.Serializable + { + ... + + @Override + public E get(int index) { + ... + } + + @Override + public E set(int index, E element) { + ... + } + + @Override + public int indexOf(Object o) { + ... + } + + @Override + public boolean contains(Object o) { + ... + } + + @Override + public void forEach(Consumer action) { + ... + } + + @Override + public void replaceAll(UnaryOperator operator) { + ... + } + + @Override + public void sort(Comparator c) { + ... + } + } +``` + +我们再看一下`java.util.AbstractList`的 `add/remove/clear` 方法就知道为什么会抛出 `UnsupportedOperationException` 了。 + +```java +public E remove(int index) { + throw new UnsupportedOperationException(); +} +public boolean add(E e) { + add(size(), e); + return true; +} +public void add(int index, E element) { + throw new UnsupportedOperationException(); +} + +public void clear() { + removeRange(0, size()); +} +protected void removeRange(int fromIndex, int toIndex) { + ListIterator it = listIterator(fromIndex); + for (int i=0, n=toIndex-fromIndex; i List arrayToList(final T[] array) { + final List l = new ArrayList(array.length); + + for (final T s : array) { + l.add(s); + } + return l; +} + + +Integer [] myArray = { 1, 2, 3 }; +System.out.println(arrayToList(myArray).getClass());//class java.util.ArrayList +``` + +2、最简便的方法 + +```java +List list = new ArrayList<>(Arrays.asList("a", "b", "c")) +``` + +3、使用 Java8 的 `Stream`(推荐) + +```java +Integer [] myArray = { 1, 2, 3 }; +List myList = Arrays.stream(myArray).collect(Collectors.toList()); +//基本类型也可以实现转换(依赖boxed的装箱操作) +int [] myArray2 = { 1, 2, 3 }; +List myList = Arrays.stream(myArray2).boxed().collect(Collectors.toList()); +``` + +4、使用 Guava + +对于不可变集合,你可以使用[`ImmutableList`](https://github.com/google/guava/blob/master/guava/src/com/google/common/collect/ImmutableList.java)类及其[`of()`](https://github.com/google/guava/blob/master/guava/src/com/google/common/collect/ImmutableList.java#L101)与[`copyOf()`](https://github.com/google/guava/blob/master/guava/src/com/google/common/collect/ImmutableList.java#L225)工厂方法:(参数不能为空) + +```java +List il = ImmutableList.of("string", "elements"); // from varargs +List il = ImmutableList.copyOf(aStringArray); // from array +``` + +对于可变集合,你可以使用[`Lists`](https://github.com/google/guava/blob/master/guava/src/com/google/common/collect/Lists.java)类及其[`newArrayList()`](https://github.com/google/guava/blob/master/guava/src/com/google/common/collect/Lists.java#L87)工厂方法: + +```java +List l1 = Lists.newArrayList(anotherListOrCollection); // from collection +List l2 = Lists.newArrayList(aStringArray); // from array +List l3 = Lists.newArrayList("or", "string", "elements"); // from varargs +``` + +5、使用 Apache Commons Collections + +```java +List list = new ArrayList(); +CollectionUtils.addAll(list, str); +``` + +6、 使用 Java9 的 `List.of()`方法 + +```java +Integer[] array = {1, 2, 3}; +List list = List.of(array); +``` \ No newline at end of file diff --git a/docs/java/collection/Java集合框架常见面试题.md b/docs/java/collection/Java集合框架常见面试题.md index f81b7097..41c72de1 100644 --- a/docs/java/collection/Java集合框架常见面试题.md +++ b/docs/java/collection/Java集合框架常见面试题.md @@ -313,7 +313,7 @@ Output: `LinkedHashSet` 是 `HashSet` 的子类,能够按照添加的顺序遍历; -`TreeSet` 底层使用红黑树,能够按照添加元素的顺序进行遍历,排序的方式有自然排序和定制排序。 +`TreeSet` 底层使用红黑树,元素是有序的,排序的方式有自然排序和定制排序。 ## 1.4 Collection 子接口之 Queue diff --git a/docs/java/jvm/JDK监控和故障处理工具总结.md b/docs/java/jvm/JDK监控和故障处理工具总结.md index c8263de0..779ab01f 100644 --- a/docs/java/jvm/JDK监控和故障处理工具总结.md +++ b/docs/java/jvm/JDK监控和故障处理工具总结.md @@ -24,12 +24,12 @@ 这些命令在 JDK 安装目录下的 bin 目录下: -- **`jps`** (JVM Process Status): 类似 UNIX 的 `ps` 命令。用户查看所有 Java 进程的启动类、传入参数和 Java 虚拟机参数等信息; -- **`jstat`**( JVM Statistics Monitoring Tool): 用于收集 HotSpot 虚拟机各方面的运行数据; -- **`jinfo`** (Configuration Info for Java) : Configuration Info forJava,显示虚拟机配置信息; -- **`jmap`** (Memory Map for Java) :生成堆转储快照; -- **`jhat`** (JVM Heap Dump Browser ) : 用于分析 heapdump 文件,它会建立一个 HTTP/HTML 服务器,让用户可以在浏览器上查看分析结果; -- **`jstack`** (Stack Trace for Java):生成虚拟机当前时刻的线程快照,线程快照就是当前虚拟机内每一条线程正在执行的方法堆栈的集合。 +- **`jps`** (JVM Process Status): 类似 UNIX 的 `ps` 命令。用于查看所有 Java 进程的启动类、传入参数和 Java 虚拟机参数等信息; +- **`jstat`**(JVM Statistics Monitoring Tool): 用于收集 HotSpot 虚拟机各方面的运行数据; +- **`jinfo`** (Configuration Info for Java) : Configuration Info for Java,显示虚拟机配置信息; +- **`jmap`** (Memory Map for Java) : 生成堆转储快照; +- **`jhat`** (JVM Heap Dump Browser) : 用于分析 heapdump 文件,它会建立一个 HTTP/HTML 服务器,让用户可以在浏览器上查看分析结果; +- **`jstack`** (Stack Trace for Java) : 生成虚拟机当前时刻的线程快照,线程快照就是当前虚拟机内每一条线程正在执行的方法堆栈的集合。 ### `jps`:查看所有 Java 进程 @@ -88,7 +88,7 @@ jstat -