String、StringBuffer、StringBuilder的对比
# String、StringBuffer、StringBuilder 的对比
# 概述
Java 提供了 String、StringBuffer 和 StringBuilder 类来封装字符串,并提供了一系列操作字符串对象的方法。
三者的共同点是都用来封装字符串、都实现了 CharSequence 接口、底层都使用 char[]存储。但是它们之间也存在不同点。
# 三者部分源码
# String 部分源码
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence
{
private final char value[];
private int hash; // Default to 0
private static final long serialVersionUID = -6849794470754667710L;
private static final ObjectStreamField[] serialPersistentFields =
new ObjectStreamField[0];
public String()
{
this.value = "".value;
}
public String(String original)
{
this.value = original.value;
this.hash = original.hash;
}
public String(char value[]) {
this.value = Arrays.copyOf(value, value.length);
}
public boolean equals(Object anObject)
{
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
public int hashCode() {
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value;
for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
}
public int indexOf(int ch) {
return indexOf(ch, 0);
}
...
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# StringBuffer 部分源码
public final class StringBuffer
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence
{
private transient char[] toStringCache;
static final long serialVersionUID = 3388685877147921107L;
public StringBuffer() {
super(16);
}
public StringBuffer(int capacity) {
super(capacity);
}
public StringBuffer(String str) {
super(str.length() + 16);
append(str);
}
public StringBuffer(CharSequence seq) {
this(seq.length() + 16);
append(seq);
}
...
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# StringBuilder 部分源码
public final class StringBuilder
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence
{
static final long serialVersionUID = 4383685877147921099L;
public StringBuilder() {
super(16);
}
public StringBuilder(int capacity) {
super(capacity);
}
public StringBuilder(String str) {
super(str.length() + 16);
append(str);
}
public StringBuilder(CharSequence seq) {
this(seq.length() + 16);
append(seq);
}
...
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 1.是否可变?
String 是被 final 修饰的,是不可变的字符序列,是字符串常量,即使调用 String 的concat 方法,也只是把字符串拼接起来,把拼接后的 String 的值赋给新创建的对象。
StringBuffer 和 StringBuilder 是可变的字符序列,是字符串变量,类的对象能够被多次的修改,并且不产生新的未使用对象。
1
2
3
2
3
# 2.线程是否安全?
String中的对象是不可变的,是被final修饰的,是字符串常量,是线程安全的。
StringBuffer对象在缓冲区被多个线程使用时,它的中的方法大都使用了synchronized 关键字进行修饰,加了同步锁,所以是线程安全的。
StringBuilder是jdk5.0新增的,在使用时没有被synchronized 关键字修饰,不能保证线程安全,可能会出现一些操作错误。
AbstractStringBuilder是StringBuilder和StringBuffer的公共父类,定义了一些字符串的基本操作,它们的用法基本相同。
多线程情况下建议使用StringBuffer,单线程建议使用速度较快的StringBuilder。
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# 3.执行效率
StringBuilder最高,StringBuffer次之,String最低。
1
# 4.初始化方式
创建String对象时,可以利用构造方法String str = new String("haha")的方式来对其进行初始化,也可以直接用赋值的方式String s = "haha"来进行初始化。而StringBuffer只能使用构造方法StringBuffer sb = new StringBuffer("hahaha")的方式来进行初始化。
1
# 5.是否实现了 hashCode 和 equals 方法
String实现了equals和hashCode方法,new String("haha").equals(new String("haha"))的结果为true;
而StringBuffer没有实现equals和hashCode方法,new StringBuffer("heihei").equals(new StringBuffer("heihei"))的结果为false。
1
2
3
2
3
# 6.使用场景
由于 StringBuilder 相较于 StringBuffer 有速度优势,所以多数情况下建议使用 StringBuilder 类。
然而在应用程序要求线程安全的情况下,则必须使用 StringBuffer 类。 append方法与直接使用+串联相比,减少常量池的浪费。
一般而言,如果要操作少量的数据时,优先使用String类;如果是在单线程下操作大量数据,优先使用StringBuilder类;如果是在多线程下操作大量的数据,优先使用StringBuilder类。
1
2
3
4
5
2
3
4
5
完善页面 (opens new window)
上次更新: 2023-12-26 18:29:08