mirror of
https://github.com/Snailclimb/JavaGuide
synced 2025-08-01 16:28:03 +08:00
[docs update]typo
This commit is contained in:
parent
7cf404ba59
commit
1c404b8340
@ -508,7 +508,7 @@ MySQL 可以简单分为 Server 层和存储引擎层这两层。Server 层处
|
|||||||
|
|
||||||
MySQL 5.7 可以通过查询 `sys` 库的 `schema_unused_indexes` 视图来查询哪些索引从未被使用。
|
MySQL 5.7 可以通过查询 `sys` 库的 `schema_unused_indexes` 视图来查询哪些索引从未被使用。
|
||||||
|
|
||||||
### 知道如何分析语句是否走索引查询
|
### 知道如何分析 SQL 语句是否走索引查询
|
||||||
|
|
||||||
我们可以使用 `EXPLAIN` 命令来分析 SQL 的 **执行计划** ,这样就知道语句是否命中索引了。执行计划是指一条 SQL 语句在经过 MySQL 查询优化器的优化会后,具体的执行方式。
|
我们可以使用 `EXPLAIN` 命令来分析 SQL 的 **执行计划** ,这样就知道语句是否命中索引了。执行计划是指一条 SQL 语句在经过 MySQL 查询优化器的优化会后,具体的执行方式。
|
||||||
|
|
||||||
|
@ -779,29 +779,33 @@ String s2 = new String("abc");
|
|||||||
|
|
||||||
### String#intern 方法有什么作用?
|
### String#intern 方法有什么作用?
|
||||||
|
|
||||||
`String.intern()` 是一个 native(本地)方法,其作用是将指定的字符串对象的引用保存在字符串常量池中,可以简单分为两种情况:
|
`String.intern()` 是一个 `native` (本地) 方法,用来处理字符串常量池中的字符串对象引用。它的工作流程可以概括为以下两种情况:
|
||||||
|
|
||||||
- 如果字符串常量池中保存了对应的字符串对象的引用,就直接返回该引用。
|
1. **常量池中已有相同内容的字符串对象**:如果字符串常量池中已经有一个与调用 `intern()` 方法的字符串内容相同的 `String` 对象,`intern()` 方法会直接返回常量池中该对象的引用。
|
||||||
- 如果字符串常量池中没有保存了对应的字符串对象的引用,那就在常量池中创建一个指向该字符串对象的引用并返回。
|
2. **常量池中没有相同内容的字符串对象**:如果字符串常量池中还没有一个与调用 `intern()` 方法的字符串内容相同的对象,`intern()` 方法会将当前字符串对象的引用添加到字符串常量池中,并返回该引用。
|
||||||
|
|
||||||
|
总结:
|
||||||
|
|
||||||
|
- `intern()` 方法的主要作用是确保字符串引用在常量池中的唯一性。
|
||||||
|
- 当调用 `intern()` 时,如果常量池中已经存在相同内容的字符串,则返回常量池中已有对象的引用;否则,将该字符串添加到常量池并返回其引用。
|
||||||
|
|
||||||
示例代码(JDK 1.8) :
|
示例代码(JDK 1.8) :
|
||||||
|
|
||||||
```java
|
```java
|
||||||
// 在堆中创建字符串对象”Java“
|
// s1 指向字符串常量池中的 "Java" 对象
|
||||||
// 将字符串对象”Java“的引用保存在字符串常量池中
|
|
||||||
String s1 = "Java";
|
String s1 = "Java";
|
||||||
// 直接返回字符串常量池中字符串对象”Java“对应的引用
|
// s2 也指向字符串常量池中的 "Java" 对象,和 s1 是同一个对象
|
||||||
String s2 = s1.intern();
|
String s2 = s1.intern();
|
||||||
// 会在堆中在单独创建一个字符串对象
|
// 在堆中创建一个新的 "Java" 对象,s3 指向它
|
||||||
String s3 = new String("Java");
|
String s3 = new String("Java");
|
||||||
// 直接返回字符串常量池中字符串对象”Java“对应的引用
|
// s4 指向字符串常量池中的 "Java" 对象,和 s1 是同一个对象
|
||||||
String s4 = s3.intern();
|
String s4 = s3.intern();
|
||||||
// s1 和 s2 指向的是堆中的同一个对象
|
// s1 和 s2 指向的是同一个常量池中的对象
|
||||||
System.out.println(s1 == s2); // true
|
System.out.println(s1 == s2); // true
|
||||||
// s3 和 s4 指向的是堆中不同的对象
|
// s3 指向堆中的对象,s4 指向常量池中的对象,所以不同
|
||||||
System.out.println(s3 == s4); // false
|
System.out.println(s3 == s4); // false
|
||||||
// s1 和 s4 指向的是堆中的同一个对象
|
// s1 和 s4 都指向常量池中的同一个对象
|
||||||
System.out.println(s1 == s4); //true
|
System.out.println(s1 == s4); // true
|
||||||
```
|
```
|
||||||
|
|
||||||
### String 类型的变量和常量做“+”运算时发生了什么?
|
### String 类型的变量和常量做“+”运算时发生了什么?
|
||||||
@ -882,6 +886,7 @@ public static String getStr() {
|
|||||||
## 参考
|
## 参考
|
||||||
|
|
||||||
- 深入解析 String#intern:<https://tech.meituan.com/2014/03/06/in-depth-understanding-string-intern.html>
|
- 深入解析 String#intern:<https://tech.meituan.com/2014/03/06/in-depth-understanding-string-intern.html>
|
||||||
|
- Java String 源码解读:<http://keaper.cn/2020/09/08/java-string-mian-mian-guan/>
|
||||||
- R 大(RednaxelaFX)关于常量折叠的回答:<https://www.zhihu.com/question/55976094/answer/147302764>
|
- R 大(RednaxelaFX)关于常量折叠的回答:<https://www.zhihu.com/question/55976094/answer/147302764>
|
||||||
|
|
||||||
<!-- @include: @article-footer.snippet.md -->
|
<!-- @include: @article-footer.snippet.md -->
|
||||||
|
@ -454,7 +454,7 @@ void afterNodeInsertion(boolean evict) { // possibly remove eldest
|
|||||||
|
|
||||||
## LinkedHashMap 和 HashMap 遍历性能比较
|
## LinkedHashMap 和 HashMap 遍历性能比较
|
||||||
|
|
||||||
`LinkedHashMap` 维护了一个双向链表来记录数据插入的顺序,因此在迭代遍历生成的迭代器的时候,是按照双向链表的路径进行遍历的。这一点相比于 `HashMap` 那种遍历整个 bucket 的方式来说,高效需多。
|
`LinkedHashMap` 维护了一个双向链表来记录数据插入的顺序,因此在迭代遍历生成的迭代器的时候,是按照双向链表的路径进行遍历的。这一点相比于 `HashMap` 那种遍历整个 bucket 的方式来说,高效许多。
|
||||||
|
|
||||||
这一点我们可以从两者的迭代器中得以印证,先来看看 `HashMap` 的迭代器,可以看到 `HashMap` 迭代键值对时会用到一个 `nextNode` 方法,该方法会返回 next 指向的下一个元素,并会从 next 开始遍历 bucket 找到下一个 bucket 中不为空的元素 Node。
|
这一点我们可以从两者的迭代器中得以印证,先来看看 `HashMap` 的迭代器,可以看到 `HashMap` 迭代键值对时会用到一个 `nextNode` 方法,该方法会返回 next 指向的下一个元素,并会从 next 开始遍历 bucket 找到下一个 bucket 中不为空的元素 Node。
|
||||||
|
|
||||||
@ -484,7 +484,7 @@ void afterNodeInsertion(boolean evict) { // possibly remove eldest
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
相比之下 `LinkedHashMap` 的迭代器则是直接使用通过 `after` 指针快速定位到当前节点的后继节点,简洁高效需多。
|
相比之下 `LinkedHashMap` 的迭代器则是直接使用通过 `after` 指针快速定位到当前节点的后继节点,简洁高效许多。
|
||||||
|
|
||||||
```java
|
```java
|
||||||
final class LinkedEntryIterator extends LinkedHashIterator
|
final class LinkedEntryIterator extends LinkedHashIterator
|
||||||
@ -550,7 +550,7 @@ System.out.println("linkedHashMap get time: " + (end - start));
|
|||||||
System.out.println(num);
|
System.out.println(num);
|
||||||
```
|
```
|
||||||
|
|
||||||
从输出结果来看,因为 `LinkedHashMap` 需要维护双向链表的缘故,插入元素相较于 `HashMap` 会更耗时,但是有了双向链表明确的前后节点关系,迭代效率相对于前者高效了需多。不过,总体来说却别不大,毕竟数据量这么庞大。
|
从输出结果来看,因为 `LinkedHashMap` 需要维护双向链表的缘故,插入元素相较于 `HashMap` 会更耗时,但是有了双向链表明确的前后节点关系,迭代效率相对于前者高效了许多。不过,总体来说却别不大,毕竟数据量这么庞大。
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
map time putVal: 5880
|
map time putVal: 5880
|
||||||
|
Loading…
x
Reference in New Issue
Block a user