diff --git a/notes/HTTP.md b/notes/HTTP.md index 82c4a36a..7238542e 100644 --- a/notes/HTTP.md +++ b/notes/HTTP.md @@ -803,7 +803,7 @@ DELETE /idX/delete HTTP/1.1 -> Returns 404 2. HTTP/1.1 支持管线化处理 3. HTTP/1.1 支持虚拟主机 4. HTTP/1.1 新增状态码 100 -5. HTTP/1.1 只是分块传输编码 +5. HTTP/1.1 支持分块传输编码 6. HTTP/1.1 新增缓存处理指令 max-age 具体内容见上文 @@ -828,7 +828,7 @@ HTTP/1.1 的解析是基于文本的,而 HTTP/2.0 采用二进制格式。 # 参考资料 -- 上野宣. 图解 HTTP[M]. Ren min you dian chu ban she, 2014. +- 上野宣. 图解 HTTP[M]. 人民邮电出版社, 2014. - [MDN : HTTP](https://developer.mozilla.org/en-US/docs/Web/HTTP) - [Are http:// and www really necessary?](https://www.webdancers.com/are-http-and-www-necesary/) - [HTTP (HyperText Transfer Protocol)](https://www.ntu.edu.sg/home/ehchua/programming/webprogramming/HTTP_Basics.html) diff --git a/notes/JDK 中的设计模式.md b/notes/JDK 中的设计模式.md index 8e2161cc..92f53cb3 100644 --- a/notes/JDK 中的设计模式.md +++ b/notes/JDK 中的设计模式.md @@ -44,11 +44,11 @@ java.awt.Desktop#getDesktop() ## 2. 简单工厂模式 -在不对用户暴露对象内部逻辑的前提下创建对象;使用通用的接口来创建对象; +在不对用户暴露对象内部逻辑的前提下创建对象。 ## 3. 工厂方法模式 -定义创建对象的接口,但是让子类来决定应该使用哪个类来创建;使用通用的接口来创建对象; +定义创建对象的接口,但是让子类来决定应该使用哪个类来创建。 ```java java.lang.Proxy#newProxyInstance() @@ -120,7 +120,7 @@ javax.swing.Action ## 3. 解释器模式 为语言创建解释器,通常由语言的语法和语法分析来定义。 - + ```java java.util.Pattern java.text.Normalizer @@ -229,7 +229,7 @@ JDBC ## 3. 组合模式 -将对象组合成树形结构来表示整理-部分层次关系,允许用户以相同的方式处理单独对象和组合对象。 +将对象组合成树形结构来表示整体-部分层次关系,允许用户以相同的方式处理单独对象和组合对象。 ```java javax.swing.JComponent#add(Component) diff --git a/notes/Java 基础.md b/notes/Java 基础.md index 50a18405..aa33ce32 100644 --- a/notes/Java 基础.md +++ b/notes/Java 基础.md @@ -12,7 +12,7 @@ * [访问权限](#访问权限) * [抽象类与接口](#抽象类与接口) * [super](#super) - * [重载与重写](#重载与重写) + * [覆盖与重载](#覆盖与重载) * [五、String](#五string) * [String, StringBuffer and StringBuilder](#string,-stringbuffer-and-stringbuilder) * [String 不可变的原因](#string-不可变的原因) @@ -55,7 +55,7 @@ y.a = 1; 声明方法不能被子类覆盖。 -private 方法隐式地被指定为 final,如果在子类中定义的方法和基类中的一个 private 方法签名相同,此时子类的方法不是覆盖基类方法,而是重载了。 +private 方法隐式地被指定为 final,如果在子类中定义的方法和基类中的一个 private 方法签名相同,此时子类的方法不是覆盖基类方法,而是在子类中定义了一个新的方法。 **3. 类** @@ -255,9 +255,9 @@ public class EqualExample { ## hashCode() -hasCode() 返回散列值,而 equals() 是用来判断两个实例是否相等。相等的两个实例散列值一定要相同,但是散列值相同的两个实例不一定相等。 +hasCode() 返回散列值,而 equals() 是用来判断两个实例是否等价。等价的两个实例散列值一定要相同,但是散列值相同的两个实例不一定等价。 -在覆盖 equals() 方法时应当总是覆盖 hashCode() 方法,保证相等的两个实例散列值也相等。 +在覆盖 equals() 方法时应当总是覆盖 hashCode() 方法,保证相等的两个实例散列值也等价。 下面的代码中,新建了两个等价的实例,并将它们添加到 HashSet 中。我们希望将这两个实例当成一样的,只在集合中添加一个实例,但是因为 EqualExample 没有实现 hasCode() 方法,因此这两个实例的散列值是不同的,最终导致集合添加了两个等价的实例。 @@ -313,7 +313,7 @@ ToStringExample@4554617c **1. cloneable** -clone() 是 Object 的受保护方法,这意味着,如果一个类不显式去重载 clone() 就没有这个方法。 +clone() 是 Object 的受保护方法,这意味着,如果一个类不显式去覆盖 clone() 就没有这个方法。 ```java public class CloneExample { @@ -327,7 +327,7 @@ CloneExample e1 = new CloneExample(); CloneExample e2 = e1.clone(); // 'clone()' has protected access in 'java.lang.Object' ``` -接下来重载 Object 的 clone() 得到以下实现: +接下来覆盖 Object 的 clone() 得到以下实现: ```java public class CloneExample { @@ -595,7 +595,7 @@ ac2.func1(); 从 Java 8 开始,接口也可以拥有默认的方法实现,这是因为不支持默认方法的接口的维护成本太高了。在 Java 8 之前,如果一个接口想要添加新的方法,那么要修改所有实现了该接口的类。 -接口也可以包含域,并且这些域隐式都是 static 和 final 的。 +接口也可以包含字段,并且这些字段隐式都是 static 和 final 的。 接口中的方法默认都是 public 的,并且不允许定义为 private 或者 protected。 @@ -636,7 +636,7 @@ System.out.println(InterfaceExample.x); - 从设计层面上看,抽象类提供了一种 IS-A 关系,那么就必须满足里式替换原则,即子类对象必须能够替换掉所有父类对象。而接口更像是一种 LIKE-A 关系,它只是提供一种方法实现契约,并不要求子类和父类具有 IS-A 关系; - 从使用上来看,一个类可以实现多个接口,但是不能继承多个抽象类。 -- 接口的域只能是 static 和 final 类型的,而抽象类的域可以有多种访问权限。 +- 接口的字段只能是 static 和 final 类型的,而抽象类的域可以有多种访问权限。 - 接口的方法只能是 public 的,而抽象类的方法可以由多种访问权限。 **4. 使用选择** @@ -706,11 +706,11 @@ SuperExtendExample.func() > [Using the Keyword super](https://docs.oracle.com/javase/tutorial/java/IandI/super.html) -## 重载与重写 +## 覆盖与重载 -- 重写存在于继承体系中,指子类实现了一个与父类在方法声明上完全相同的一个方法; +- 覆盖(Override)存在于继承体系中,指子类实现了一个与父类在方法声明上完全相同的一个方法; -- 重载即存在于继承体系中,也存在于同一个类中,指一个方法与已经存在的方法或者父类的方法名称上相同,但是参数类型、个数、顺序至少有一个不同。应该注意的是,返回值不同,其它都相同不算是重载。 +- 重载(Overload)存在于同一个类中,指一个方法与已经存在的方法名称上相同,但是参数类型、个数、顺序至少有一个不同。应该注意的是,返回值不同,其它都相同不算是重载。 # 五、String @@ -739,7 +739,7 @@ SuperExtendExample.func() 如果一个 String 对象已经被创建过了,那么就会从 String Pool 中取得引用。只有 String 是不可变的,才可能使用 String Pool。 -

+

**3. 安全性** @@ -773,7 +773,7 @@ String s5 = "bbb"; System.out.println(s4 == s5); // true ``` -Java 虚拟机将堆划分成新生代、老年代和永久代(PermGen Space)。在 Java 6 之前,字符串常量池被放在永久代中,而在 Java 7 时,它被放在堆的其它位置。这是因为永久代的空间有限,如果大量使用字符串的场景下会导致 OutOfMemoryError 错误。 +Java 虚拟机将堆划分成新生代、老年代和永久代(PermGen Space)。在 Java 7 之前,字符串常量池被放在永久代中,而在 Java 7,它被放在堆的其它位置。这是因为永久代的空间有限,如果大量使用字符串的场景下会导致 OutOfMemoryError 错误。 > [What is String interning?](https://stackoverflow.com/questions/10578984/what-is-string-interning)
[深入解析 String#intern](https://tech.meituan.com/in_depth_understanding_string_intern.html) @@ -946,7 +946,7 @@ Throwable 可以用来表示任何可以作为异常抛出的类,分为两种 1. **受检异常** :需要用 try...catch... 语句捕获并进行处理,并且可以从异常中恢复; 2. **非受检异常** :是程序运行时错误,例如除 0 会引发 Arithmetic Exception,此时程序奔溃并且无法恢复。 -

+

> [Java 入门之异常处理](https://www.tianmaying.com/tutorial/Java-Exception)
[Java 异常的面试问题及答案 -Part 1](http://www.importnew.com/7383.html) diff --git a/notes/Java 容器.md b/notes/Java 容器.md index 7c31b8a2..1cb19fe6 100644 --- a/notes/Java 容器.md +++ b/notes/Java 容器.md @@ -567,7 +567,7 @@ static final int DEFAULT_CONCURRENCY_LEVEL = 16;

-### 2. HashEntery 的不可变性 +### 2. HashEntry 的不可变性 HashEntry 中的 key,hash,next 都声明为 final 型。这意味着,不能把节点添加到链接的中间和尾部,也不能在链接的中间和尾部删除节点。这个特性可以保证:在访问某个节点时,这个节点之后的链接不会被改变。这个特性可以大大降低处理链表时的复杂性。 diff --git a/notes/Java 并发.md b/notes/Java 并发.md index 742d6408..a1131c9c 100644 --- a/notes/Java 并发.md +++ b/notes/Java 并发.md @@ -76,7 +76,7 @@ ## 无限期等待(Waiting) -等待其它线程显示地唤醒,否则不会被分配 CPU 时间片。 +等待其它线程显式地唤醒,否则不会被分配 CPU 时间片。 | 进入方法 | 退出方法 | | --- | --- | @@ -794,9 +794,10 @@ public class SemaphoreExample { try { semaphore.acquire(); System.out.print(semaphore.availablePermits() + " "); - semaphore.release(); } catch (InterruptedException e) { e.printStackTrace(); + } finally { + semaphore.release(); } }); } @@ -1413,7 +1414,7 @@ ABA :如果一个变量 V 初次读取的时候是 A 值,它的值被改成 **(二)栈封闭** -多个线程方法同一个方法的局部变量时,不会出现线程安全问题,因为局部变量存储在栈中,属于线程私有的。 +多个线程访问同一个方法的局部变量时,不会出现线程安全问题,因为局部变量存储在栈中,属于线程私有的。 ```java import java.util.concurrent.ExecutorService; diff --git a/notes/MySQL.md b/notes/MySQL.md index 99fc6797..5cc1fd69 100644 --- a/notes/MySQL.md +++ b/notes/MySQL.md @@ -40,7 +40,7 @@ InnoDB 是 MySQL 默认的事务型存储引擎,只有在需要 InnoDB 不支 ## MyISAM -MyISAM 提供了大量的特性,包括全文索引、压缩、空间函数(GIS)等。但 MyISAM 不支持事务和行级锁,而且崩溃后无法安全恢复。 +MyISAM 提供了大量的特性,包括全文索引、压缩、空间函数(GIS)等。但 MyISAM 不支持事务和行级锁,而且崩溃后无法安全恢复。应该注意的是,MySQL5.6.4 添加了对 InnoDB 引擎的全文索引支持。 只能对整张表加锁,而不是针对行。 @@ -62,7 +62,7 @@ MyISAM 设计简单,数据以紧密格式存储,所以在某些场景下性 2. 备份:InnoDB 支持在线热备份。 3. 崩溃恢复:MyISAM 崩溃后发生损坏的概率比 InnoDB 高很多,而且恢复的速度也更慢。 4. 并发:MyISAM 只支持表级锁,而 InnoDB 还支持行级锁。 -5. 其它特性:MyISAM 支持全文索引,地理空间索引。 +5. 其它特性:MyISAM 支持,地理空间索引。 # 二、数据类型 diff --git a/notes/分布式基础.md b/notes/分布式基础.md index b3ce172e..f7f77498 100644 --- a/notes/分布式基础.md +++ b/notes/分布式基础.md @@ -95,7 +95,7 @@ **一致性哈希** -Distributed Hash Table(DHT):对于哈希空间 0\~2n,将该哈希空间看成一个哈希环,将每个节点都配置到哈希环上。每个数据对象通过哈希取模得到哈希值之后,存放到哈希环中顺时针方向第一个大于等于该哈希值的节点上。 +Distributed Hash Table(DHT):对于哈希空间 [0, 2n-1],将该哈希空间看成一个哈希环,将每个节点都配置到哈希环上。每个数据对象通过哈希取模得到哈希值之后,存放到哈希环中顺时针方向第一个大于等于该哈希值的节点上。

diff --git a/notes/剑指 offer 题解.md b/notes/剑指 offer 题解.md index 8af879a1..4a6c375c 100644 --- a/notes/剑指 offer 题解.md +++ b/notes/剑指 offer 题解.md @@ -82,7 +82,7 @@ # 2. 实现 Singleton -> [单例模式](https://github.com/CyC2018/Interview- Notebook/blob/master/notes/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F.md) +> [单例模式](https://github.com/CyC2018/Interview-Notebook/blob/master/notes/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F.md) # 3. 数组中重复的数字 @@ -1142,7 +1142,7 @@ public ListNode Merge(ListNode list1, ListNode list2) { ListNode head = new ListNode(-1); ListNode cur = head; while (list1 != null && list2 != null) { - if (list1.val < list2.val) { + if (list1.val <= list2.val) { cur.next = list1; list1 = list1.next; } else { @@ -1409,7 +1409,7 @@ public ArrayList> Print(TreeNode pRoot) { ## 题目描述 -输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。 +输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。假设输入的数组的任意两个数字都互不相同。 例如,下图是后序遍历序列 3,1,2 所对应的二叉搜索树。 @@ -1673,36 +1673,30 @@ public ArrayList GetLeastNumbers_Solution(int[] nums, int k) { int kthSmallest = findKthSmallest(nums, k - 1); ArrayList ret = new ArrayList<>(); for (int val : nums) { - if (val <= kthSmallest && ret.size() < k) ret.add(val); + if (val <= kthSmallest && ret.size() < k) { + ret.add(val); + } } return ret; } public int findKthSmallest(int[] nums, int k) { - int l = 0; - int h = nums.length - 1; + int l = 0, h = nums.length - 1; while (l < h) { int j = partition(nums, l, h); - if (j < k) { - l = j + 1; - } else if (j > k) { - h = j - 1; - } else { - break; - } + if (j == k) break; + if (j > k) h = j - 1; + else l = j + 1; } return nums[k]; } private int partition(int[] nums, int l, int h) { - int i = l; - int j = h + 1; + int i = l, j = h + 1; while (true) { while (i < h && nums[++i] < nums[l]) ; while (j > l && nums[l] < nums[--j]) ; - if (i >= j) { - break; - } + if (i >= j) break; swap(nums, i, j); } swap(nums, l, j); @@ -1710,9 +1704,7 @@ private int partition(int[] nums, int l, int h) { } private void swap(int[] nums, int i, int j) { - int t = nums[i]; - nums[i] = nums[j]; - nums[j] = t; + int t = nums[i]; nums[i] = nums[j]; nums[j] = t; } ``` @@ -1882,7 +1874,7 @@ private int getAmountOfDigit(int digit) { } /** - * 在 digit 位数组成的字符串中,第 index 为的数 + * 在 digit 位数组成的字符串中,第 index 个数 */ private int digitAtIndex(int index, int digit) { int number = beginNumber(digit) + index / digit; @@ -1994,6 +1986,7 @@ public int longestSubStringWithoutDuplication(String str) { int curLen = 0; int maxLen = 0; int[] indexs = new int[26]; + Arrays.fill(indexs, -1); for (int i = 0; i < str.length(); i++) { int c = str.charAt(i) - 'a'; int preIndex = indexs[c]; @@ -2018,21 +2011,19 @@ public int longestSubStringWithoutDuplication(String str) { ## 解题思路 ```java -public int GetUglyNumber_Solution(int N) { - if (N <= 6) return N; +public int GetUglyNumber_Solution(int index) { + if (index <= 6) return index; int i2 = 0, i3 = 0, i5 = 0; - int cnt = 1; - int[] dp = new int[N]; + int[] dp = new int[index]; dp[0] = 1; - while (cnt < N) { + for (int i = 1; i < index; i++) { int n2 = dp[i2] * 2, n3 = dp[i3] * 3, n5 = dp[i5] * 5; - int min = Math.min(n2, Math.min(n3, n5)); - dp[cnt++] = min; - if (min == n2) i2++; - if (min == n3) i3++; - if (min == n5) i5++; + dp[i] = Math.min(n2, Math.min(n3, n5)); + if (dp[i] == n2) i2++; + if (dp[i] == n3) i3++; + if (dp[i] == n5) i5++; } - return dp[N - 1]; + return dp[index - 1]; } ``` diff --git a/notes/数据库系统原理.md b/notes/数据库系统原理.md index 46b5e1b8..134c60fa 100644 --- a/notes/数据库系统原理.md +++ b/notes/数据库系统原理.md @@ -307,7 +307,7 @@ InnoDB 的 MVCC 使用到的快照存储在 Undo 日志中,该日志通过回 ### 4. UPDATE -将系统版本号作为更新后的数据行快照的创建版本号,同时将系统版本号作为作为更新前的数据行快照的删除版本号。可以理解为先执行 DELETE 后执行 INSERT。 +将系统版本号作为更新后的数据行快照的创建版本号,同时将系统版本号作为更新前的数据行快照的删除版本号。可以理解为先执行 DELETE 后执行 INSERT。 ## 快照读与当前读 @@ -401,7 +401,7 @@ SELECT c FROM t WHERE c BETWEEN 10 and 20 FOR UPDATE; 1. 冗余数据,例如学生-2 出现了两次。 2. 修改异常,修改了一个记录中的信息,但是另一个记录中相同的信息却没有被修改。 -3. 删除异常,删除一个信息,那么也会丢失其它信息。例如如果删除了课程-1,需要删除第二行和第三行,那么学生-1 的信息就会丢失。 +3. 删除异常,删除一个信息,那么也会丢失其它信息。例如如果删除了课程-1,需要删除第一行和第三行,那么学生-1 的信息就会丢失。 4. 插入异常,例如想要插入一个学生的信息,如果这个学生还没选课,那么就无法插入。 ## 范式 diff --git a/notes/算法.md b/notes/算法.md index 161c2e79..997dc245 100644 --- a/notes/算法.md +++ b/notes/算法.md @@ -1439,7 +1439,7 @@ public class Transaction{ ### 3. 基于线性探测法的散列表 -线性探测法使用空位来解决冲突,当冲突发生时,向前探测一个空位来存储冲突的键。使用线程探测法,数组的大小 M 应当大于键的个数 N(M>N)。 +线性探测法使用空位来解决冲突,当冲突发生时,向前探测一个空位来存储冲突的键。使用线性探测法,数组的大小 M 应当大于键的个数 N(M>N)。

diff --git a/notes/设计模式.md b/notes/设计模式.md index 21ce516f..b7e6c76a 100644 --- a/notes/设计模式.md +++ b/notes/设计模式.md @@ -276,13 +276,12 @@ public class ConcreteFactory2 extends Factory { 抽象工厂模式创建的是对象家族,也就是很多对象而不是一个对象,并且这些对象是相关的,也就是说必须一起创建出来。而工厂模式只是用于创建一个对象,这和抽象工厂模式有很大不同。 -抽象工厂模式用到了工厂模式来创建单一对象,在类图左部,AbstractFactory 中的 createProductA 和 createProductB 方法都是让子类来实现,这两个方法单独来看就是在创建一个对象,这符合工厂模式的定义。 +抽象工厂模式用到了工厂模式来创建单一对象,AbstractFactory 中的 createProductA 和 createProductB 方法都是让子类来实现,这两个方法单独来看就是在创建一个对象,这符合工厂模式的定义。 至于创建对象的家族这一概念是在 Client 体现,Client 要通过 AbstractFactory 同时调用两个方法来创建出两个对象,在这里这两个对象就有很大的相关性,Client 需要同时创建出这两个对象。 从高层次来看,抽象工厂使用了组合,即 Cilent 组合了 AbstractFactory,而工厂模式使用了继承。 - ## 代码实现 ```java