String、StringBuffer和StringBuilder的区别
类型方面:
字符串类 类型 String 字符串常量 StringBuffer 字符串变量 StringBuilder 字符串变量 代码1
String s = "Hello"; s = s + "World"; System.out.println(s);//输出HelloWorld
- String是字符串常量,是不可变类,任何对String的改变都会引发新的String对象的生成。所以以上代码:先创建对象s,赋予值Hello,然后再创建一个新的对象s,赋值HelloWorld,也就是原来的对象s并没有发生改变。
- 由于String是不可改变的对象,所以用String操作字符串时,实际上是在不断创建新的对象,原来的对象会变成垃圾被GC回收掉,所以大量操作String执行效率会非常低。
代码2
StringBuffer sb = new StringBuffer("Hello"); sb.append(" java !"); System.out.println(sb);//Hello java ! StringBuilder sb2 = new StringBuilder("Hello"); sb2.append(" java").append(" !"); System.out.println(sb2);//Hello java !
- StringBuffer和StringBuilder都是可变类,任何对其字符串的改变都不会产生新的对象,所以执行速度快。
执行速度方面:
StringBuilder > StringBuffer > String直接上代码
package com.java.string; public class StringBufferBuilder { public static String BASE = "Java"; public static final int COUNT = 1000000; /** * 执行String赋值测试 */ public static void stringTest() { String str = new String(BASE); long start = System.currentTimeMillis(); for (int i = 0; i < COUNT / 100; i++) {//缩小100倍 str = str + "great"; } long end = System.currentTimeMillis(); System.out.println("String赋值时间:" + (end - start)); } /** * 执行StringBuffer赋值测试 */ public static void stringBufferTest() { StringBuffer str = new StringBuffer(BASE); long start = System.currentTimeMillis(); for (int i = 0; i < COUNT; i++) { str = str.append("great"); } long end = System.currentTimeMillis(); System.out.println("StringBuffer赋值时间:" + (end - start)); } /** * 执行StringBuilder赋值测试 */ public static void stringBuilderTest() { StringBuilder str = new StringBuilder(BASE); long start = System.currentTimeMillis(); for (int i = 0; i < COUNT; i++) { str = str.append("great"); } long end = System.currentTimeMillis(); System.out.println("StringBuilder赋值时间:" + (end - start)); } public static void main(String[] args) { /* * 输出: * String赋值时间:271 * StringBuffer赋值时间:44 * StringBuilder赋值时间:21 */ stringTest(); stringBufferTest(); stringBuilderTest(); } }
从上面的结果可以看出,不考虑多线程,采用String对象时,即便缩小了100倍,执行时间比其他两个都要高出很多,而采用StringBuffer对象和采用StringBuilder对象的差别也比较明显。
- 线程安全方面:
- StringBuilder:线程非安全的
- StringBuffer:线程安全的
- 当我们在字符串缓冲区被多个线程使用时,JVM不能保证StringBuilder的操作是安全的,虽然它速度最快,但是可以保证StringBuffer是可以正确操作的。当然大多数情况下就是我们是在单线程下进行的操作,所以大多数情况下是建议用StringBuilder而不用StringBuffer的,就是速度的原因。
对于三者使用的总结:
- 如果要操作少量的数据 == String
- 单线程操作字符串缓冲区下操作大量数据 == StringBuilder
- 多线程操作字符串缓冲区下操作大量数据 == StringBuffer
StringBuffer和StringBuilder常用方法摘要
方法 | 功能 |
---|---|
append(object) | 将object参数的字符串表示形式追加到序列 末尾,类似于字符串连接。 |
delete(int start,int end) | 移除此序列的子字符串中的字符(从start处 开始,一直到索引 end-1处的字符)。 |
deleteCharAt(int index) | 移除此序列指定位置的 char。 |
insert(int offset,Object obj) | 将Object参数的字符串表示形式插入在此字符序列中。 |
reverse() | 将此字符串反转。 |
setCharAt(int index, char ch) | 将给定索引处的字符设置为ch。 |
charAt(int index) | 返回此序列中指定索引处的char值。 |
indexOf(String str) | 返回第一次出现的指定字符串在该字符串 中的索引。 |
substring(int start) | 返回一个新的 String,它包含此字符序列 当前所包含的字符子序列。 |
substring(int start,int end) | 返回一个新的 String,它包含此序列当前 所包含的字符子序列。 |
toString() | 返回此序列中数据的字符串表示形式。 |
replace(int start, int end, String str) | 使用给定 String 中的字符替换此序列 的子字符串中的字符。 |
String常用方法摘要
参考引用:
API在线文档
StringBuffer与StringBuilder区别?
String、StringBuffer与StringBuilder之间区别?