一、先明确基础前提
StringBuffer和StringBuilder的 API几乎完全一致(仅StringBuffer方法加了synchronized),因此下面会把二者归为「可变字符串类」统一讲解,重点区分与StringAPI 的差异。
二、核心 API 详解(附示例)
1. String 核心 API(不可变字符串)
String的方法均返回新的 String 对象,原对象不会被修改,以下是高频使用的方法:
| 方法签名 | 功能说明 | 示例代码 |
|---|---|---|
char charAt(int index) | 获取指定索引的字符(索引从 0 开始) | String str = "hello"; char c = str.charAt(1); // c = 'e' |
int length() | 获取字符串长度 | str.length(); // 5 |
boolean isEmpty() | 判断字符串是否为空(长度为 0) | "" .isEmpty(); // true |
String concat(String str) | 拼接字符串(等价于 “+”,返回新对象) | String s = str.concat(" world"); // s = "hello world" |
String substring(int begin) | 截取从 begin 到末尾的子串 | str.substring(2); // "llo" |
String substring(int begin, int end) | 截取 [begin, end) 区间的子串(左闭右开) | str.substring(1,4); // "ell" |
boolean equals(Object obj) | 比较字符串内容是否相等(区分大小写) | "hello".equals("Hello"); // false |
boolean equalsIgnoreCase(String str) | 忽略大小写比较内容 | "Hello".equalsIgnoreCase("hello"); // true |
int indexOf(String str) | 查找子串首次出现的索引,无则返回 -1 | str.indexOf("l"); // 2 |
int lastIndexOf(String str) | 查找子串最后出现的索引,无则返回 -1 | str.lastIndexOf("l"); // 3 |
String replace(char old, char new) | 替换所有指定字符 | str.replace('l', 'x'); // "hexxo" |
String replaceAll(String regex, String replacement) | 正则替换 | "a1b2c3".replaceAll("\\d", "*"); // "a*b*c*" |
String[] split(String regex) | 按正则分割字符串为数组 | "a,b,c".split(","); // ["a","b","c"] |
String toUpperCase() | 转大写 | str.toUpperCase(); // "HELLO" |
String toLowerCase() | 转小写 | str.toLowerCase(); // "hello" |
String trim() | 去除首尾空白字符(JDK11+ 可用strip()支持全角空白) | " hello ".trim(); // "hello" |
boolean startsWith(String prefix) | 判断是否以指定前缀开头 | str.startsWith("he"); // true |
boolean endsWith(String suffix) | 判断是否以指定后缀结尾 | str.endsWith("lo"); // true |
2. StringBuilder / StringBuffer 核心 API(可变字符串)
二者方法完全一致,核心是直接修改原对象,返回值为this(支持链式调用),高频方法如下:
| 方法签名 | 功能说明 | 示例代码(以 StringBuilder 为例) |
|---|---|---|
| 构造方法 | ||
StringBuilder() | 空构造,初始容量 16 字符 | StringBuilder sb = new StringBuilder(); |
StringBuilder(String str) | 用指定字符串初始化,容量 = 16 + str.length() | StringBuilder sb = new StringBuilder("hello"); // 容量 21 |
StringBuilder(int capacity) | 指定初始容量(避免频繁扩容,优化性能) | StringBuilder sb = new StringBuilder(100); // 初始容量 100 |
| 核心修改方法 | ||
StringBuilder append(任意类型) | 拼接任意类型数据(int、String、char[] 等),最常用 | sb.append(" world").append(123); // "hello world123" |
StringBuilder insert(int offset, 任意类型) | 在指定索引插入数据 | sb.insert(5, ","); // "hello, world123" |
StringBuilder delete(int start, int end) | 删除 [start, end) 区间的字符 | sb.delete(5,6); // "hello world123" |
StringBuilder deleteCharAt(int index) | 删除指定索引的字符 | sb.deleteCharAt(10); // "hello world23" |
StringBuilder replace(int start, int end, String str) | 替换指定区间字符 | sb.replace(6,11, "java"); // "hello java123" |
StringBuilder reverse() | 反转字符串 | sb.reverse(); // "321avaj olleh" |
| 辅助方法 | ||
int length() | 获取当前字符长度(实际字符数) | sb.length(); // 11 |
int capacity() | 获取当前数组容量(底层 char[] 长度) | sb.capacity(); // 21(初始 21,未扩容时) |
void ensureCapacity(int min) | 手动扩容,确保容量 ≥ min | sb.ensureCapacity(50); // 容量变为 50 |
void setLength(int newLength) | 设置字符串长度(不足补 ‘\0’,超出截断) | sb.setLength(5); // "hello" |
char charAt(int index) | 获取指定索引字符(同 String) | sb.charAt(1); // 'e' |
void setCharAt(int index, char c) | 修改指定索引的字符 | sb.setCharAt(1, 'x'); // "hxllo" |
String toString() | 转为不可变的 String 对象(最终输出/存储时用) | String result = sb.toString(); // "hxllo" |
3. 关键 API 对比(易混点)
| 操作场景 | String 方法 | 可变字符串方法 | 核心差异 |
|---|---|---|---|
| 拼接字符串 | concat()/ “+” | append() | String 造新对象,可变类改原对象 |
| 替换字符 | replace()(返回新对象) | replace()(改原对象) | 前者无区间替换,后者支持区间 |
| 截取字符串 | substring()(返回新对象) | 无直接截取方法(可先 delete 再 toString) | String 更便捷 |
| 反转字符串 | 需手动实现(如循环) | reverse() | 可变类原生支持,效率高 |
三、API 实战示例(综合场景)
场景 1:单线程拼接海量字符串(用 StringBuilder)
publicclassStringBuilderDemo{publicstaticvoidmain(String[]args){// 初始化时指定容量,避免扩容StringBuildersb=newStringBuilder(100000);// 循环拼接 10 万次(效率远高于 String)for(inti=0;i<100000;i++){sb.append("用户ID:").append(i).append(",状态:正常\n");}// 插入表头sb.insert(0,"=== 用户列表 ===\n");// 替换指定内容sb.replace(0,11,"=== 最新用户列表 ===");// 转为 String 输出Stringresult=sb.toString();System.out.println(result.substring(0,100));// 打印前 100 个字符}}场景 2:多线程拼接(用 StringBuffer)
publicclassStringBufferDemo{publicstaticvoidmain(String[]args)throwsInterruptedException{StringBuffersbf=newStringBuffer();// 10 个线程,每个拼接 1000 次for(inti=0;i<10;i++){newThread(()->{for(intj=0;j<1000;j++){sbf.append("数据").append(j).append(";");}}).start();}Thread.sleep(1000);// 等待线程执行完毕System.out.println("最终拼接长度:"+sbf.length());// 稳定输出(线程安全)System.out.println("最后 100 字符:"+sbf.substring(sbf.length()-100));}}场景 3:String 高频 API 组合使用
publicclassStringApiDemo{publicstaticvoidmain(String[]args){Stringstr=" 张三,25,男;李四,30,女;王五,28,男 ";// 1. 去除首尾空白str=str.trim();// 2. 按分号分割为用户字符串数组String[]users=str.split(";");// 3. 遍历处理每个用户for(Stringuser:users){// 4. 按逗号分割用户信息String[]info=user.split(",");Stringname=info[0];intage=Integer.parseInt(info[1]);Stringgender=info[2];// 5. 拼接并输出格式化信息System.out.printf("姓名:%s,年龄:%d,性别:%s%n",name,age,gender);}// 6. 查找是否包含"李四"booleanhasLi=str.contains("李四");System.out.println("是否包含李四:"+hasLi);// true// 7. 替换所有性别为"男"的为"男性"StringnewStr=str.replaceAll("男","男性");System.out.println("替换后:"+newStr);// 张三,25,男性;李四,30,女;王五,28,男性}}总结
- String API:核心是「查询/只读」,所有修改方法均返回新对象,适合字符串常量、少量拼接、内容查询场景;
- StringBuilder/StringBuffer API:核心是「修改/写入」,
append()/insert()/reverse()等方法直接修改原对象,支持链式调用,StringBuilder单线程优先,StringBuffer多线程使用; - 性能优化:使用可变字符串时,提前指定初始容量(
new StringBuilder(容量))可避免频繁扩容,大幅提升效率。
记住核心用法:查用 String,改(单线程)用 StringBuilder,改(多线程)用 StringBuffer。