1. 核心替换方法
// 单次区间替换(StringBuffer原生方法)
public StringBuffer replace(int start, int end, String str)
2. 实现 replaceAll() 功能
方案1:转换为String操作(简单但低效)
StringBuffer sb = new StringBuffer("apple banana apple");
String result = sb.toString().replaceAll("apple", "orange");
sb = new StringBuffer(result); // 重新构建StringBuffer
方案2:手动循环替换(高效推荐)
public static void replaceAll(StringBuffer sb, String target, String replacement) {
int index = 0;
int targetLen = target.length();
int replacementLen = replacement.length();
while ((index = sb.indexOf(target, index)) != -1) {
sb.replace(index, index + targetLen, replacement);
index += replacementLen; // 跳过已替换部分
}
}
// 使用示例
StringBuffer sb = new StringBuffer("apple banana apple");
replaceAll(sb, "apple", "orange");
// 结果: "orange banana orange"
3. 使用技巧
大小写不敏感替换
public static void replaceAllIgnoreCase(StringBuffer sb, String target, String replacement) { String lowerSb = sb.toString().toLowerCase(); String lowerTarget = target.toLowerCase(); int index = 0; while ((index = lowerSb.indexOf(lowerTarget, index)) != -1) { sb.replace(index, index + target.length(), replacement); index += replacement.length(); // 更新小写副本的对应区间 lowerSb = sb.toString().toLowerCase(); } }
正则表达式替换
// 通过String的replaceAll实现 StringBuffer sb = new StringBuffer("123-456-789"); String result = sb.toString().replaceAll("\\d{3}", "***"); sb = new StringBuffer(result); // "***-***-***"
链式批量替换
public static StringBuffer chainReplace(StringBuffer sb, String... pairs) { for (int i = 0; i < pairs.length; i += 2) { if (i + 1 >= pairs.length) break; replaceAll(sb, pairs[i], pairs[i + 1]); } return sb; } // 使用示例 chainReplace(sb, "apple", "orange", "banana", "grape");
4. 常见错误
死循环替换
// 错误:replacement包含target replaceAll(sb, "a", "aa"); // 无限循环!
索引错位
// 错误:未更新index导致重复替换 while ((index = sb.indexOf("a")) != -1) { sb.replace(index, index+1, "b"); // 缺少 index += replacement.length() }
正则特殊字符未转义
replaceAll(sb, "$price", "10"); // $在正则中有特殊含义
5. 注意事项
线程安全
// 多线程环境需要同步 synchronized(sb) { replaceAll(sb, "data", "DATA"); }
Unicode字符处理
// 正确计算代理对字符长度 String emoji = "😊"; int emojiLen = emoji.codePointCount(0, emoji.length());
性能敏感场景
// 10万次操作耗时对比: // String.replaceAll(): ~120ms // 手动StringBuffer替换: ~25ms
6. 最佳实践与性能优化
预扫描优化(减少操作次数)
public static void replaceAllOptimized(StringBuffer sb, String target, String replacement) { int index = 0; int targetLen = target.length(); int step = replacement.length(); List<Integer> positions = new ArrayList<>(); // 第一阶段:收集所有位置 while ((index = sb.indexOf(target, index)) != -1) { positions.add(index); index += targetLen; } // 第二阶段:倒序替换(避免索引变动) for (int i = positions.size()-1; i >= 0; i--) { int pos = positions.get(i); sb.replace(pos, pos + targetLen, replacement); } }
大文本处理(内存优化)
public static void replaceInChunks(StringBuffer sb, String target, String replacement) { final int CHUNK_SIZE = 4096; // 4K块 for (int i = 0; i < sb.length(); i += CHUNK_SIZE) { int end = Math.min(i + CHUNK_SIZE + target.length(), sb.length()); String chunk = sb.substring(i, end); if (chunk.contains(target)) { String updated = chunk.replace(target, replacement); sb.replace(i, end, updated); } } }
直接操作字符数组(极限优化)
public static void replaceAllCharLevel(StringBuffer sb, String target, String replacement) { char[] tarArr = target.toCharArray(); char[] repArr = replacement.toCharArray(); char[] srcArr = new char[sb.length()]; sb.getChars(0, sb.length(), srcArr, 0); StringBuilder result = new StringBuilder(); int i = 0; while (i < srcArr.length) { boolean match = true; for (int j = 0; j < tarArr.length; j++) { if (i + j >= srcArr.length || srcArr[i + j] != tarArr[j]) { match = false; break; } } if (match) { result.append(repArr); i += tarArr.length; } else { result.append(srcArr[i++]); } } sb.setLength(0); sb.append(result); }
总结
场景 | 推荐方案 | 性能特点 |
---|---|---|
简单少量替换 | toString().replaceAll() |
代码简洁,效率较低 |
频繁修改的缓冲区 | 手动replace() 循环 |
最佳性能(O(n)) |
超大文本(>1MB) | 分块处理 | 避免OOM,中等性能 |
正则表达式需求 | 转换为String操作 | 功能强大,性能差 |
内存极度敏感场景 | 字符数组直接操作 | 零拷贝,最高效 |