第 11 章:String 与 StringBuilder
学习目标
- 掌握 String 的常用方法和不可变性
- 学会 StringBuilder 高效拼接
- 避开字符串比较和拼接的常见坑
一、String 不可变
String 是不可变的——每次修改都创建新对象。
java
String s = "hello";
s = s + " world"; // ⚠️ 不是改 s,而是创建新对象,让 s 指向新对象
// 原 "hello" 对象会被 GC 回收含义:String 可以安全地当作 HashMap 的 key / HashSet 的元素(因为不会变)。
二、String 常用方法
java
String s = "Hello, World!";
s.length() // 13
s.charAt(0) // 'H'
s.substring(0, 5) // "Hello"
s.indexOf("World") // 7
s.contains("Hello") // true
s.startsWith("Hello") // true
s.endsWith("!") // true
s.replace("World", "Java") // "Hello, Java!"
s.split(",") // ["Hello", " World!"]
s.trim() // 去首尾空格
s.toLowerCase() // 小写
s.toUpperCase() // 大写
s.isEmpty() // false(length == 0)
s.equals("hello, world!") // false(区分大小写)
s.equalsIgnoreCase("HELLO, WORLD!") // true三、字符串比较(永远用 equals)
⚠️ 坑 1:字符串比较永远用
equals,不要用==。javaString a = new String("hi"); String b = new String("hi"); a == b // ❌ false(地址不同) a.equals(b) // ✅ true(值相同)
==比的是内存地址,equals比的是内容。企业代码只用equals。
四、StringBuilder(高频拼接用)
字符串用 + 拼接,每次都创建新对象。循环里拼接用 StringBuilder(性能差 100 倍)。
java
// ❌ 慢:循环 1000 次 = 1000 次 new String
String result = "";
for (int i = 0; i < 1000; i++) {
result += i;
}
// ✅ 快:StringBuilder
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++) {
sb.append(i);
}
String result = sb.toString();链式调用:
java
String s = new StringBuilder()
.append("Hello")
.append(" ")
.append("World")
.toString();⚠️ 坑 2:循环里用
+拼接字符串是性能杀手,日志拼接、SQL 拼接都用 StringBuilder。
五、StringBuilder vs StringBuffer
| 维度 | StringBuilder | StringBuffer |
|---|---|---|
| 线程安全 | ❌ 不安全 | ✅ 安全 |
| 性能 | 快 | 慢 |
| 场景 | 单线程(99%) | 多线程 |
默认用 StringBuilder,需要线程安全时再用 StringBuffer(其实现在多用 StringBuilder + 外部锁)。
六、实战:字符串拼接场景
java
// 1. 简单拼接(不在循环):直接用 +
String greeting = "Hello, " + name + "!";
// 2. 循环拼接:用 StringBuilder
StringBuilder html = new StringBuilder();
for (Item item : items) {
html.append("<li>").append(item.getName()).append("</li>");
}
// 3. 日志拼接:用 String.format 或 占位符
String log = String.format("用户 %s 下单,金额 %d", name, price);七、本章小结
| 要点 | 关键 |
|---|---|
| String 不可变 | 修改都是创建新对象,原对象会被 GC |
| equals | 字符串比较永远用 equals,不用 == |
| StringBuilder | 循环拼接必须用,性能差 100 倍 |
| StringBuffer | 多线程场景用,单线程用 StringBuilder |
动手练习
- 字符串反转:用 StringBuilder 实现
reverse(String s) - 字符串去重:用
indexOf实现removeDuplicates(String s),返回无重复字符的字符串 - 效率对比:写两段代码(循环拼接 vs StringBuilder),比较 10000 次拼接的耗时