String和StringBuilder
String 拼接字符串
class Solution {
public String toLowerCase(String s) {
String res = "";
for (char c : s.toCharArray()) {
if (c >= 'A' && c <= 'Z')
res += (char)(c - 'A' + 'a');
else
res += c;
}
return res;
}
}
StringBuider
看下StringBuilder的威力
class Solution {
public String toLowerCase(String s) {
StringBuilder res = new StringBuilder();
for (char c : s.toCharArray()) {
if (c >= 'A' && c <= 'Z')
res.append((char)(c - 'A' + 'a'));
else
res.append(c);
}
return res.toString();
}
}
String的方式底层是如何使用拼接的
反编译class文件,留意行号
javap查看字节码信息
42: new #4 // class java/lang/StringBuilder
45: dup
46: invokespecial #5 // Method java/lang/StringBuilder."<init>":()V
49: aload_2
50: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
53: iload 6
55: bipush 65
57: isub
58: bipush 97
60: iadd
61: i2c
62: invokevirtual #7 // Method java/lang/StringBuilder.append:(C)Ljava/lang/StringBuilder;
65: invokevirtual #8 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
68: astore_2
69: goto 92
72: new #4 // class java/lang/StringBuilder
75: dup
76: invokespecial #5 // Method java/lang/StringBuilder."<init>":()V
79: aload_2
80: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
83: iload 6
85: invokevirtual #7 // Method java/lang/StringBuilder.append:(C)Ljava/lang/StringBuilder;
88: invokevirtual #8 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
LineNumberTable:
line 12: 0
line 13: 3
line 14: 28
line 15: 42
line 17: 72
line 13: 92
line 19: 98
- 分析看出在代码15行的地方创建了一个StringBuilder对象,然后调用append方法
- 在第17行的时候也创建了一个StringBuilder对象,然后调用append方法
- 也就是说每次循环到 15,17 都创建了一个StringBuilder对象,然后调用append和toString
相当于
public String toLowerCase(String s) {
StringBuilder res = new StringBuilder();
for (char c : s.toCharArray()) {
if (c >= 'A' && c <= 'Z')
res.append(new StringBuilder((char)(c - 'A' + 'a')).toString());
else
res.append(new StringBuilder(c).toString());
}
return res.toString();
}
再探StringBuilder方式的实现
57: invokevirtual #5 // Method java/lang/StringBuilder.append:(C)Ljava/lang/StringBuilder;
60: pop
61: goto 71
64: aload_2
65: iload 6
67: invokevirtual #5 // Method java/lang/StringBuilder.append:(C)Ljava/lang/StringBuilder;
70: pop
71: iinc 5, 1
74: goto 20
77: aload_2
78: invokevirtual #6 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
81: areturn
LineNumberTable:
line 13: 0
line 14: 8
line 15: 33
line 16: 47
line 18: 64
line 14: 71
line 20: 77
- 不难发现代码只是在多次调用append方法,相对来说节省了很多内存资源,提升了执行速度。
总结:在循环中,使用字符串拼接效率会远远低于StringBuilder,字符串的拼接底层转换成了每次创建一个StringBuilder对象