根据网课做的记录,有几句是自己的理解,如有错误欢迎指正
不考虑线程安全,单从效率上讲,StringBuilder 最高效!StringBuffer其次,String的 “ + ” 拼接最慢。
StringBuilder线程不安全,StringBuffer线程安全。
所以StringBuilder适用于单线程下在字符缓冲区进行大量操作,StringBuffer多线程下在字符缓冲区进行大量操作.
首先,要知道这样几个小知识:
1、方法区(永久代、非堆区)
- 被所有线程共享。
- 所有定义的方法的信息都存在该区域,包括静态变量、常量、类信息(构造方法、接口定义)、运行时常量池。
- 实际变量存在堆内存,与方法区无关
- 以上为逻辑上的定义,HotSpot中,方法区仅逻辑独立,实际上包含在JAV堆中,即,物理上属于JAVA堆区的一部分,永久区是方法区的实现
2、一个JVM实例只存在一个堆内容,堆在逻辑上分新生代、老年代、永久代
- 新生区:新创建的对象,垃圾回收次数 < 15次的对象
- 老年区:位于堆空间,垃圾回收次数 > 15次,还依然存活的对象
- 永久区:位于非堆空间,常驻内存区域,存放JDK自身携带的 Class、Interface 的元数据,即运行环境必须存储的类信息,一旦到了这个区域,就不会被回收掉,除非关闭JVM才会释放该区域所占的内存。
3、演变进程
- JDK1.7之前,hotspot虚拟机堆方法区的实现为永久代,运行常量池(含字符串常量池)存放在方法区。
- JDK1.7,字符串常量池拿到了堆中,运行常量池剩余的部分还在方法区(即永久代)。
- JDK1.8及之后,用“元空间”(Metaspace)取代了“永久代”;字符串常量池还在堆中,运行常量池还在方法区,只是方法区的实现从“永久代”变成了“元空间”。
4、字符串是不变的,创建后无法更改。字符串缓冲区支持可变字符串,可以共享。比如:
如果用 “ + ” 拼接,如下,输出结果必然是 abcdefghi
String text1 = "abc";
String text2 = "def";
String text3 = "ghi";
String text4 = text1 + text2 + text3;
System.out.println(text4);
text1、text2、text3在堆中分别占有三段内存
用 “+” 拼接时,分别会形成这样两段字符 “abcdef” 、 “abcdefghi”
这两段字符都会存放在堆中(字符串常量池),各自再占一块内存,如果后面不用到“abcdef”,它也不会被回收。
如果在进行大数据分析做数据采集时,大量用到 “+” 拼接,那么造成的内存垃圾可想而知,数据一旦变大,运行时间一长,必然导致卡顿。所以说它低效。
它只适用于少量的字符串操作的情况
StringBuilder拼接字符串
StringBuilder sb = new StringBuilder();
sb.append("1");
sb.append("2");
sb.append("3");
String text = sb.toString();
System.out.println(text);
输出结果如下