字符串操作在编程中的用处是非常大的,而在编程时选择哪个字符串操作呢?我们在这里比较三个,主要区别如下:
String 字符串常量
StringBuffer 字符串变量(线程安全)
StringBuilder 字符串变量(非线程安全)
操作字符串速度: StringBuilder > StringBuffer > StringBuilder
一般知道这么多久够了。但是可以分析一下原因,看源码(java1,7),String的:
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
这个是java1.7String的部分源码片段:
首先,String类是final的,不可继承。字符串实现的底层原理为char数组,但是String的char数组是final类型的,不可修改。所以在进行增加,删除,修改等操作,都会生成一个新的String。所以很慢。显然对于一个final类的变量,显然是线程安全的。
注:final修饰的变量不一定是线程安全的。
在看,StringBuilder和StringBuffer,
public final class StringBuffer
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence
public final class StringBuilder
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence
两个是不是很相似,对,父类都是一样的!其实这个两个类的具体逻辑没有多少,都是在父类 AbstractStringBuilder,看父类
abstract class AbstractStringBuilder implements Appendable, CharSequence {
/**
* The value is used for character storage.
*/
char[] value;
/**
* The count is the number of characters used.
*/
int count;
这是实现跟String差不多,都是底层为char数组,区别就是这个不是final类型,所以这就是为啥String速度是最慢的。
看同一个方法:
AbstractStringBuilder
public AbstractStringBuilder append(int i) {
if (i == Integer.MIN_VALUE) {
append("-2147483648");
return this;
}
int appendedLength = (i < 0) ? Integer.stringSize(-i) + 1
: Integer.stringSize(i);
int spaceNeeded = count + appendedLength;
ensureCapacityInternal(spaceNeeded);
Integer.getChars(i, spaceNeeded, value);
count = spaceNeeded;
return this;
}
StringBuilder
public StringBuilder append(int i) {
super.append(i);
return this;
}
StringBuffer
public synchronized StringBuffer append(int i) {
super.append(i);
return this;
}
从上面的示例可以看出,StringBuilder和StringBuffer都是调用的父类AbstractStringBuilder的方法,差别就是StringBuffer加上了关键字synchronized,而StringBuilder只是简单的封装,这就是为啥,StringBuffer是线程安全的,StringBuilder不是,这个可以解释StringBuilder的速度为啥比StringBuffer快,所以在单线程下,还是使用StringBuilder比较好,轻量级!
当然还有另外一个区别,经常犯的错误,可以先运行一下代码段
StringBuilder sb1 = new StringBuilder("123");
StringBuilder sb2 = new StringBuilder("123");
System.out.println(sb1.equals(sb2));//false
String s1 = new String("123");
String s2 = new String("123");
System.out.println(s1.equals(s2));//ture
System.out.println(sb1.equals(s1));//false
System.out.println(s1.equals(sb1));//false
System.out.println(s1.equals(sb1.toString()));//true
主要是因为,String重写了超级父类Object,而其他两个没有,String是比较字符串值,StringBuilder和StringBuffer还是在比较地址而已!!!