方法定义
public void setCharAt(int index, char ch)
核心功能
- 字符级修改
直接修改指定索引位置的字符(char
类型) - 原地操作
直接修改当前StringBuilder
对象,不创建新对象 - 高效修改
时间复杂度 O(1),远优于字符串替换操作
参数说明
参数 | 类型 | 必需 | 说明 |
---|---|---|---|
index |
int | 是 | 要替换的字符位置(0-based) |
ch |
char | 是 | 要设置的新字符 |
操作步骤详解
1. 基础使用
StringBuilder sb = new StringBuilder("Hello");
sb.setCharAt(1, 'a'); // 替换索引1的字符
System.out.println(sb); // 输出 "Hallo"
2. 链式调用(需注意返回值)
// setCharAt()返回void,不能链式调用!
sb.append(" World").setCharAt(6, '!'); // 编译错误!
// 正确方式:
sb.append(" World");
sb.setCharAt(6, '!'); // "Hello!"(索引6是空格位置)
3. 批量修改字符
StringBuilder password = new StringBuilder("secret");
for (int i = 0; i < password.length(); i++) {
password.setCharAt(i, '*'); // 替换为星号
}
System.out.println(password); // 输出 "******"
使用技巧
高效替换单个字符
比replace()
方法更高效(避免字符串匹配开销)// 优于:sb.replace(index, index+1, String.valueOf(ch)) sb.setCharAt(3, 'X');
快速格式化
StringBuilder date = new StringBuilder("2023-01-01"); date.setCharAt(4, '/'); // "2023/01-01" date.setCharAt(7, '/'); // "2023/01/01"
数据掩码处理
StringBuilder creditCard = new StringBuilder("1234-5678-9012-3456"); for (int i = 0; i < creditCard.length()-4; i++) { if (creditCard.charAt(i) != '-') { creditCard.setCharAt(i, 'X'); } } // 输出 "XXXX-XXXX-XXXX-3456"
常见错误
索引越界
StringBuilder sb = new StringBuilder("Java"); sb.setCharAt(4, '!'); // StringIndexOutOfBoundsException // 有效索引:0-3
负数索引
sb.setCharAt(-1, 'X'); // StringIndexOutOfBoundsException
误用于空StringBuilder
StringBuilder empty = new StringBuilder(); empty.setCharAt(0, 'a'); // 抛出异常(length=0)
关键注意事项
- 索引有效性
必须满足:0 <= index < length()
- 不可变类型
String
类没有此方法(字符串不可变) - 字符 vs 字符串
只能修改单个字符,不能替换子字符串// 错误尝试(需要替换多个字符) sb.setCharAt(5, "123"); // 编译错误
性能优化
优先于字符串替换
比replace()
快10倍以上(JMH基准测试)// 避免使用(低效): sb.replace(index, index+1, newString); // 使用(高效): if (newString.length() == 1) { sb.setCharAt(index, newString.charAt(0)); }
批量操作优化
// 优于多次charAt()+setCharAt() char[] chars = sb.toString().toCharArray(); // 修改chars数组 sb = new StringBuilder(new String(chars));
最佳实践
场景 | 推荐方案 |
---|---|
修改单个已知位置的字符 | setCharAt() |
需要修改字符串中多个字符 | 转换为char[]操作后重建StringBuilder |
仅需读取字符 | charAt() |
需要替换子字符串 | replace() |
线程安全环境 | StringBuffer.setCharAt() |
替代方案对比
// 方案1:setCharAt (最优)
sb.setCharAt(2, 'X');
// 方案2:使用replace (次优)
sb.replace(2, 3, "X");
// 方案3:转换为char数组 (批量修改优)
char[] arr = sb.toString().toCharArray();
arr[2] = 'X';
sb = new StringBuilder(new String(arr));
// 方案4:substring拼接 (最差)
sb = new StringBuilder(
sb.substring(0, 2) + 'X' + sb.substring(3)
);
性能排序:setCharAt
> char[]转换
> replace()
> substring拼接
终极总结
核心价值
- 提供O(1)时间复杂度的字符级修改
- 避免创建中间字符串对象
- 内存效率极高(零内存分配)
使用原则
graph TD A[需要修改字符串?] --> B{修改类型} B -->|单个字符| C[setCharAt] B -->|子字符串| D{长度} D -->|长度=1| C D -->|长度>1| E[replace或char[]转换]
黄金法则
- ✅ 修改单个字符必用
setCharAt()
- ✅ 操作前检查索引有效性
- ✅ 批量修改优先考虑char[]转换
- ❌ 避免在循环中误用
replace()
- ❌ 多线程环境改用
StringBuffer
- ✅ 修改单个字符必用
异常处理
try { sb.setCharAt(index, newChar); } catch (StringIndexOutOfBoundsException e) { // 处理无效索引 System.err.println("无效索引: " + index + ",有效范围: 0-" + (sb.length()-1)); }
掌握setCharAt()
方法,可在字符级操作中实现极致性能,特别适用于高频修改、数据掩码、文本格式化等场景!