StringBuilder.replace()
是 StringBuilder
类中用于替换指定范围字符的重要方法。它允许你高效地修改字符串内容,而无需创建新的字符串对象。
一、方法定义
public StringBuilder replace(int start, int end, String str)
参数说明:
start
:起始索引(包含),从 0 开始。end
:结束索引(不包含),即替换范围为[start, end)
。str
:要插入的字符串(可以为null
)。
返回值:
- 返回调用该方法的
StringBuilder
对象本身(支持链式调用)。
异常:
StringIndexOutOfBoundsException
:如果start < 0
、start > length()
、end < start
或end > length()
。
二、功能说明
- 核心功能:将
StringBuilder
中从索引start
到end-1
的字符子串,替换为指定的字符串str
。 - 原地修改:操作在原对象上进行,不创建新对象。
- 长度可变:替换后的字符串长度可以与原范围不同(可变长替换)。
- 支持
null
:如果str
为null
,则插入字符串"null"
。
三、示例代码
示例 1:基本替换
StringBuilder sb = new StringBuilder("Hello World");
sb.replace(6, 11, "Java");
System.out.println(sb.toString()); // 输出:Hello Java
// 将 "World"(索引 6-10)替换为 "Java"
示例 2:替换为更短的字符串
StringBuilder sb = new StringBuilder("Hello World");
sb.replace(5, 11, "!");
System.out.println(sb.toString()); // 输出:Hello!
// 原 " World" 被 "!" 替代
示例 3:替换为更长的字符串
StringBuilder sb = new StringBuilder("Hello!");
sb.replace(5, 6, " Beautiful World");
System.out.println(sb.toString()); // 输出:Hello Beautiful World!
// 在索引 5(空格位置)插入长字符串
示例 4:插入功能(start == end)
StringBuilder sb = new StringBuilder("Hello");
sb.replace(5, 5, " World");
System.out.println(sb.toString()); // 输出:Hello World
// 在末尾插入 " World",相当于 insert(5, " World")
示例 5:删除功能(替换为空字符串)
StringBuilder sb = new StringBuilder("Hello World");
sb.replace(5, 6, ""); // 或 sb.replace(5, 6, null) → 插入 "null"
System.out.println(sb.toString()); // 输出:HelloWorld
// 删除索引 5 处的空格
示例 6:链式调用
StringBuilder sb = new StringBuilder("A-B-C-D");
sb.replace(0, 1, "X")
.replace(2, 3, "Y")
.replace(4, 5, "Z");
System.out.println(sb.toString()); // 输出:X-Y-Z-D
示例 7:处理 null
StringBuilder sb = new StringBuilder("Hello");
sb.replace(5, 5, null);
System.out.println(sb.toString()); // 输出:Hellonull
// 插入字符串 "null"
四、使用技巧
技巧 1:实现“插入”功能
当 start == end
时,replace()
等效于 insert()
:
sb.replace(pos, pos, "newStr"); // 在 pos 位置插入
技巧 2:实现“删除”功能
用空字符串替换目标范围:
sb.replace(start, end, ""); // 删除 [start, end) 范围
技巧 3:批量替换(结合循环)
StringBuilder sb = new StringBuilder("Error: ERROR_CODE_1, error: ERROR_CODE_2");
// 统一替换所有 "error" 相关词为大写
int index = 0;
while ((index = sb.indexOf("error", index)) != -1) {
sb.replace(index, index + 5, "ERROR");
index += 5; // 跳过已替换部分
}
技巧 4:与 indexOf()
配合定位
StringBuilder sb = new StringBuilder("User: alice, Status: active");
int start = sb.indexOf("Status: ");
if (start != -1) {
int end = start + 8 + 6; // "Status: ".length() + "active".length()
sb.replace(start, end, "Status: inactive");
}
五、常见错误
错误 1:索引越界
StringBuilder sb = new StringBuilder("Hi");
sb.replace(5, 6, "Hello");
// 抛出 StringIndexOutOfBoundsException
// 原因:start=5 > length()=2
错误 2:end < start
sb.replace(3, 1, "test");
// 抛出 StringIndexOutOfBoundsException
错误 3:混淆“包含”与“不包含”
StringBuilder sb = new StringBuilder("Hello");
// 想替换 "llo"(索引 2,3,4),错误写法:
sb.replace(2, 4, "XX"); // 只替换索引 2,3 → "HeXXo"
// 正确写法:
sb.replace(2, 5, "XX"); // 替换索引 2,3,4 → "HeXX"
六、注意事项
- 左闭右开区间:
end
索引不包含在替换范围内,即[start, end)
。 - 自动扩容:如果替换后的总长度超过当前容量,会自动扩容。
null
处理:传入null
会被当作字符串"null"
插入。- 原地修改:方法修改原对象,不影响之前通过
toString()
生成的String
。 - 性能影响:若替换范围较小但新字符串很长,可能触发数组复制。
七、最佳实践与性能优化
1. 预判索引有效性
int len = sb.length();
if (start >= 0 && start <= len && end >= start && end <= len) {
sb.replace(start, end, str);
} else {
// 处理异常情况
}
2. 避免频繁大范围替换
- 频繁替换可能导致内部数组多次复制。
- 若需大规模重构,考虑重新构建
StringBuilder
。
3. 结合 ensureCapacity()
预分配
// 预估替换后最大长度
sb.ensureCapacity(sb.length() + expectedGrowth);
sb.replace(start, end, longString);
4. 使用 setCharAt()
替代单字符替换
// 更高效(无需数组移动)
sb.setCharAt(0, 'h');
// 而不是
// sb.replace(0, 1, "h");
5. 性能对比:replace
vs delete + append
replace(start, end, str)
内部等价于delete(start, end).insert(start, str)
。- 直接使用
replace()
更简洁,性能相同。
八、总结
要点 | 说明 |
---|---|
核心作用 | 高效替换指定范围的字符子串 |
关键参数 | start (包含)、end (不包含)、str (新字符串) |
返回值 | 自身,支持链式调用 |
异常 | StringIndexOutOfBoundsException (索引无效) |
常用技巧 | 实现插入(start==end )、删除(str="" ) |
常见错误 | 索引越界、混淆区间包含性 |
最佳实践 | 验证索引、预分配容量、避免滥用 |
性能提示 | 单字符替换用 setCharAt ,大范围修改评估成本 |
最终建议:
StringBuilder.replace()
是一个强大且高效的字符串修改工具。掌握其“左闭右开”的索引规则是避免错误的关键。在实际开发中,优先用于中等范围的文本替换、插入和删除操作。结合indexOf()
定位目标位置,能实现灵活的文本处理逻辑。记住:正确使用索引,预判边界,即可安全高效地驾驭此方法。