- String
如下图所示,String在java中被声明为final class,String的值是不可变的。这会导致String相关操作基本都会产生新的String对象,如果这样操作很多,会大量浪费内存空间,效率低下,对程序性能影响较大。
- StringBuffer
StringBuffer是为了解决大量拼接字符串时产生很多中间对象问题而提供的一个类。StringBuilder的对象是变量,对变量的操作不需要对象的产生和销毁,效率会高很多。
如下示例1 String的操作速度比StringBuffer快,这并不是String比StringBuffer快,而是第一行在java编译过程中就被优化成了“abcde”,所以快。
public class test1 {
public static void main(String[] args) {
String str="abc"+"de";
StringBuffersb=new StringBuffer().append("abc").append("de");
System.out.println(str);
System.out.println(sb.toString());
}
}
如下示例2 String的操作速度就比StringBuffer慢了,因为String操作有引用符号,涉及JVM对对象的创建和回收,速度没有StringBuffer快。
public class test1 {
public static void main(String[] args) {
String str="abc";
String s="de";
str=str+s;
StringBuffersb=new StringBuffer().append("abc").append("de");
System.out.println(str);
System.out.println(sb.toString());
}
}
Tips:这里有错误示例,如下所示就会报 Exception in thread "main" java.lang.NullPointerException
String s=“sss”;
StringBuffer sb=null;
sb.append(s);
必须要用
StringBuffer sb=new StringBuffer().append(s);
- StringBuilder
StringBuilder跟StringBuffer一样都是继承AbstractStringBuilder,区别只有StringBuffer是线程安全的,JDK1.5发现大部分场景下字符串拼接不要求线程安全,就出现了StringBuilder,去掉线程安全的部分,大大提高了效率。
三者效率测试示例如下
public class StringBuilderBuffer {
private static final int TIMES = 22222;
public static void main(String[] args) {
StringBuilderBuffer.testString();
StringBuilderBuffer.testStringBuffer();
StringBuilderBuffer.testStringBuilder();
}
/**
* String时间效率测试
*/
public static void testString() {
long startTime = System.currentTimeMillis();
String str = "";
for (int i = 0; i < TIMES; i++) {
str += "test";
}
long endTime = System.currentTimeMillis();
System.out.println("String test usedtime: " + (endTime - startTime));
}
/**
* StringBuffer时间效率测试(线程安全)
*/
public static void testStringBuffer() {
long startTime = System.currentTimeMillis();
StringBuffer str = new StringBuffer();
for (int i = 0; i < TIMES; i++) {
str.append("test");
}
long endTime = System.currentTimeMillis();
System.out.println("StringBuffer test usedtime: " + (endTime - startTime));
}
/**
* StringBuffer时间效率测试(非线程安全)
*/
public static void testStringBuilder() {
long startTime = System.currentTimeMillis();
StringBuilder str = new StringBuilder();
for (int i = 0; i < TIMES; i++) {
str.append("test");
}
long endTime = System.currentTimeMillis();
System.out.println("StringBuilder test usedtime: " + (endTime - startTime));
}
}
String test usedtime: 1177
StringBuffer test usedtime: 1
StringBuilder test usedtime: 0
Process finished with exit code 0
从结果可以看出效率上 StringBuilder > StringBuffer >> String
小结:
String:使用在字符串不经常变化,少量字符串拼接操作应用场景,使代码更清晰简洁
StringBuilder:有大量字符串拼接操作,不要求线程安全的情况下,采用StringBuilder更高效,eg:JSON处理等
StringBuffer:多线程情况下,有大量的字符串拼接操作,应该使用StringBuffer,eg:HTTP参数解析和封装等
Tips
-
java 中的length 属性是针对数组说的,比如说你声明了一个数组,想知道这个数组的长度则用到了 length 这个属性.
-
java 中的length()方法是针对字 符串String说的,如果想看这个字符串的长度则用到 length()这个方法.
-
.java 中的size()方法是针对泛型集合说的,如果想看这个泛型有多少个元素,就调用此方法来查看!
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2019.12.15 更新
- 反转字符串,用StringBuffer的reverse方法,再转回String
public class StringDemo {
public static void main(String[] args) {
String str = "abc";
String reverseStr=new StringBuffer(str).reverse().toString();
System.out.println(str);
System.out.println(reverseStr);
}
}