@@ -2489,15 +2489,15 @@ s.replace("-","");//12378
24892489* `public String(char[] chs)` : 根据字符数组的内容,来创建字符串对象
24902490* `public String(String original)` : 根据传入的字符串内容,来创建字符串对象
24912491
2492- 直接赋值:`String s = “abc”` 直接赋值的方式创建字符串对象,内容就是abc
2492+ 直接赋值:`String s = “abc”` 直接赋值的方式创建字符串对象,内容就是 abc
24932493
24942494- 通过构造方法创建:通过 new 创建的字符串对象,每一次 new 都会申请一个内存空间,虽然内容相同,但是地址值不同,**返回堆内存中对象的引用**
24952495- 直接赋值方式创建:以“ ”方式给出的字符串,只要字符序列相同(顺序和大小写),无论在程序代码中出现几次,JVM 都只会**在 String Pool 中创建一个字符串对象**,并在字符串池中维护
24962496
24972497`String str = new String("abc")`创建字符串对象:
24982498
24992499* 创建一个对象:字符串池中已经存在"abc"对象,那么直接在创建一个对象放入堆中,返回堆内引用
2500- * 创建两个对象:字符串池中未找到"abc"对象,那么分别在堆中和字符串池中创建一个对象,字符串池中的比较都是采用 equals() 方法
2500+ * 创建两个对象:字符串池中未找到"abc"对象,那么分别在堆中和字符串池中创建一个对象,字符串池中的比较都是采用 equals()
25012501 <img src="https://gitee.com/seazean/images/raw/master/Java/String构造方法字节码.png" style="zoom: 67%;" />
25022502
25032503`new String("a") + new String("b")`创建字符串对象:
@@ -2509,7 +2509,7 @@ s.replace("-","");//12378
25092509* 对象4:new String("b")、对象5:常量池中的"b"
25102510 <img src="https://gitee.com/seazean/images/raw/master/Java/String拼接方法字节码.png" style="zoom:67%;" />
25112511
2512- * StringBuilder的toString ():
2512+ * StringBuilder 的 toString ():
25132513
25142514 ```java
25152515 @Override
@@ -2533,9 +2533,9 @@ s.replace("-","");//12378
25332533
25342534**字符串常量池(String Pool / StringTable / 串池)**保存着所有字符串字面量(literal strings),这些字面量在编译时期就确定,常量池类似于Java系统级别提供的**缓存**,存放对象和引用
25352535
2536- * StringTable,hashtable (哈希表 + 链表)结构,不能扩容,默认值大小长度是1009
2536+ * StringTable,hashtable (哈希表 + 链表)结构,不能扩容,默认值大小长度是 1009
25372537* 常量池中的字符串仅是符号,第一次使用时才变为对象,可以避免重复创建字符串对象
2538- * 字符串**变量**的拼接的原理是StringBuilder (jdk1.8),append 效率要比字符串拼接高很多
2538+ * 字符串**变量**的拼接的原理是 StringBuilder (jdk1.8),append 效率要比字符串拼接高很多
25392539* 字符串**常量**拼接的原理是编译期优化,结果在常量池
25402540* 可以使用 String 的 intern() 方法在运行过程将字符串添加到 String Pool 中
25412541
@@ -2564,7 +2564,7 @@ public class Demo {
25642564 String s2 = "b";
25652565 String s3 = "ab";//串池
25662566 // new StringBuilder().append("a").append("b").toString() new String("ab")
2567- String s4 = s1 + s2; // 堆内地址
2567+ String s4 = s1 + s2; // 返回的是堆内地址
25682568 String s5 = "a" + "b"; // javac 在编译期间的优化,结果已经在编译期确定为ab
25692569
25702570 System.out.println(s3 == s4); // false
@@ -2586,8 +2586,8 @@ public class Demo {
25862586结论:
25872587
25882588```java
2589- String s1 = "ab"; //串池
2590- String s2 = new String("a") + new String("b"); //堆
2589+ String s1 = "ab"; //放入串池
2590+ String s2 = new String("a") + new String("b"); //放入堆
25912591//上面两条指令的结果和下面的 效果 相同
25922592String s = new String("ab");
25932593```
@@ -2621,7 +2621,7 @@ public static void main(String[] args) {
26212621```java
26222622public static void main(String[] args) {
26232623 String str1 = new StringBuilder("58").append("tongcheng").toString();
2624- System.out.println(str1 == str1.intern());//true
2624+ System.out.println(str1 == str1.intern());//true,字符串池中不存在,把堆中的引用复制一份放入串池
26252625
26262626 String str2 = new StringBuilder("ja").append("va").toString();
26272627 System.out.println(str2 == str2.intern());//false
@@ -2743,13 +2743,13 @@ public class Demo1_25 {
27432743#### 不可变好处
27442744
27452745* 可以缓存 hash 值
2746- 因为 String 的 hash 值经常被使用,例如 String 用做 HashMap 的 key。不可变的特性可以使得 hash 值也不可变,只需要进行一次计算
2746+ String 的 hash 值经常被使用,例如 String 用做 HashMap 的 key。不可变的特性可以使得 hash 值也不可变,只要进行一次计算
27472747* String Pool 的需要
2748- 如果一个String对象已经被创建过了,就会从 String Pool中取得引用。 只有 String是不可变的,才可能使用 String Pool
2748+ 如果一个String对象已经被创建过了,就会从 String Pool 中取得引用, 只有 String是不可变的,才可能使用 String Pool
27492749* 安全性
27502750 String 经常作为参数,String 不可变性可以保证参数不可变。例如在作为网络连接参数的情况下如果 String 是可变的,那么在网络连接过程中,String 被改变,改变 String 的那一方以为现在连接的是其它主机,而实际情况却不一定是
27512751* String 不可变性天生具备线程安全,可以在多个线程中安全地使用
2752- * 防止子类继承,破坏String的API的使用
2752+ * 防止子类继承,破坏 String 的 API 的使用
27532753
27542754
27552755
@@ -2765,7 +2765,7 @@ String StringBuffer 和 StringBuilder 区别:
27652765
27662766* String : **不可变**的字符序列,线程安全
27672767* StringBuffer : **可变**的字符序列,线程安全,底层方法加 synchronized,效率低
2768- * StringBuilder : **可变**的字符序列,JDK5.0新增 ;线程不安全,效率高
2768+ * StringBuilder : **可变**的字符序列,JDK5.0 新增 ;线程不安全,效率高
27692769
27702770相同点:底层使用 char[] 存储
27712771
@@ -3942,6 +3942,10 @@ public static void main(String[] args){
39423942
39433943
39443944
3945+ ***
3946+
3947+
3948+
39453949###### 源码
39463950
39473951ArrayList 实现类集合底层**基于数组存储数据**的,查询快,增删慢,支持快速随机访问
@@ -3970,7 +3974,7 @@ public class ArrayList<E> extends AbstractList<E>
39703974 }
39713975 ```
39723976
3973- 当add 第 1 个元素到 ArrayList,size 是 0,进入 ensureCapacityInternal 方法,
3977+ 当 add 第 1 个元素到 ArrayList,size 是 0,进入 ensureCapacityInternal 方法,
39743978
39753979 ```java
39763980 private void ensureCapacityInternal(int minCapacity) {
@@ -4043,12 +4047,17 @@ public class ArrayList<E> extends AbstractList<E>
40434047* 删除元素:需要调用 System.arraycopy() 将 index+1 后面的元素都复制到 index 位置上,在旧数组上操作,该操作的时间复杂度为 O(N),可以看到 ArrayList 删除元素的代价是非常高的,
40444048
40454049 ```java
4046- private void fastRemove(Object[] es, int i) {
4050+ public E remove(int index) {
4051+ rangeCheck(index);
40474052 modCount++;
4048- final int newSize;
4049- if ((newSize = size - 1) > i)
4050- System.arraycopy(es, i + 1, es, i, newSize - i);
4051- es[size = newSize] = null;
4053+ E oldValue = elementData(index);
4054+
4055+ int numMoved = size - index - 1;
4056+ if (numMoved > 0)
4057+ System.arraycopy(elementData, index+1, elementData, index, numMoved);
4058+ elementData[--size] = null; // clear to let GC do its work
4059+
4060+ return oldValue;
40524061 }
40534062 ```
40544063
@@ -4073,7 +4082,7 @@ public class ArrayList<E> extends AbstractList<E>
40734082
40744083* **Fail-Fast**:快速失败,modCount 用来记录 ArrayList **结构发生变化**的次数,结构发生变化是指添加或者删除至少一个元素的所有操作,或者是调整内部数组的大小,仅仅只是设置元素的值不算结构发生变化
40754084
4076- 在进行序列化或者迭代等操作时,需要比较操作前后 modCount 是否改变,如果改变了抛出 ConcurrentModificationException异常
4085+ 在进行序列化或者迭代等操作时,需要比较操作前后 modCount 是否改变,改变了抛出 ConcurrentModificationException 异常
40774086
40784087
40794088
@@ -4626,7 +4635,11 @@ JDK7 对比 JDK8:
46264635 * **当链表长度超过(大于)阈值(或者红黑树的边界值,默认为 8)并且当前数组的长度大于等于64时,此索引位置上的所有数据改为红黑树存储**
46274636 * 即使哈希函数取得再好,也很难达到元素百分百均匀分布。当 HashMap 中有大量的元素都存放到同一个桶中时,就相当于一个长的单链表,假如单链表有 n 个元素,遍历的**时间复杂度是 O(n)**,所以 JDK1.8 中引入了 红黑树(查找**时间复杂度为 O(logn)**)来优化这个问题,使得查找效率更高
46284637
4629- 
4638+ 
4639+
4640+
4641+
4642+ 参考视频:https://www.bilibili.com/video/BV1nJ411J7AA
46304643
46314644
46324645
@@ -9774,7 +9787,7 @@ Heap 堆:是JVM内存中最大的一块,由所有线程共享,由垃圾回
97749787* 对象实例:类初始化生成的对象,**基本数据类型的数组也是对象实例**,new 创建对象都使用堆内存
97759788* 字符串常量池:
97769789 * 字符串常量池原本存放于方法区,jdk7开始放置于堆中
9777- * 字符串常量池**存储的是 string 对象的直接引用或者对象**,是一张 string table
9790+ * 字符串常量池**存储的是 String 对象的直接引用或者对象**,是一张 string table
97789791* 静态变量:静态变量是有 static 修饰的变量,jdk7 时从方法区迁移至堆中
97799792* 线程分配缓冲区 Thread Local Allocation Buffer:线程私有但不影响堆的共性,可以提升对象分配的效率
97809793
0 commit comments