我们来系统地梳理一下 Java 中的字符串操作。Java 的字符串操作非常丰富,主要涉及到 String
、StringBuilder
和 StringBuffer
这三个核心类。
目录
一、核心类简介
二、String 类的常用操作
1. 创建字符串
2. 获取基本信息
3. 比较字符串
4. 查找与判断
5. 转换与替换
6. 分割与连接
三、StringBuilder / StringBuffer 的常用操作
1. 创建对象
2. 修改字符串(核心功能)
四、性能对比:+ 拼接 vs StringBuilder
1.错误示例:使用 + 拼接
2.正确示例:使用 StringBuilder
一、核心类简介
在开始具体操作前,先理解这三个类的区别至关重要:
import java.lang.StringBuilder;
类 | 特性 | 线程安全 | 性能 | 适用场景 |
---|---|---|---|---|
String | 不可变 (Immutable) | 是 | 较低(每次修改都创建新对象) | 字符串内容不需要改变的场景,如作为常量、Map 的键等。 |
StringBuilder | 可变 (Mutable) | 否 | 最高 | 单线程环境下,需要频繁修改字符串内容(拼接、删除、替换等)。 |
StringBuffer | 可变 (Mutable) | 是 | 较低(因为有同步开销) | 多线程环境下,需要安全地修改字符串内容。 |
核心结论:
- 如果字符串内容不改变,用
String
。 - 如果在单线程下需要频繁修改字符串,用
StringBuilder
。 - 如果在多线程下需要安全地修改字符串,用
StringBuffer
。
二、String
类的常用操作
String
类提供了大量用于处理字符串的方法。
1. 创建字符串
// 1. 直接赋值 (推荐,JVM 会有字符串常量池优化)
String str1 = "Hello Java";// 2. 使用 new 关键字 (会创建新的对象,不推荐)
String str2 = new String("Hello Java");
2. 获取基本信息
String str = "Hello World";
System.out.println(str.length()); // 获取长度: 11
System.out.println(str.isEmpty()); // 判断是否为空字符串: false
System.out.println(str.charAt(0)); // 获取指定索引的字符: 'H'
System.out.println(str.indexOf('W')); // 查找字符 'W' 的索引: 6
System.out.println(str.indexOf("World")); // 查找子串 "World" 的索引: 6
System.out.println(str.lastIndexOf('o')); // 从后向前查找字符 'o' 的索引: 7
3. 比较字符串
String s1 = "hello";
String s2 = "world";
String s3 = "Hello";// 1. equals() : 比较内容是否相等 (区分大小写)
System.out.println(s1.equals(s2)); // false// 2. equalsIgnoreCase() : 比较内容是否相等 (不区分大小写)
System.out.println(s1.equalsIgnoreCase(s3)); // true// 3. compareTo() : 比较字典顺序
// s1 < s2 返回负数, s1 == s2 返回 0, s1 > s2 返回正数
System.out.println(s1.compareTo(s2)); // -15 (h 的 ASCII 码比 w 小)// 4. == : 比较的是两个对象的内存地址 (是否是同一个对象)
String s4 = "hello";
String s5 = new String("hello");
System.out.println(s1 == s4); // true (字符串常量池,指向同一个对象)
System.out.println(s1 == s5); // false (new 创建了新对象,地址不同)
4. 查找与判断
String str = "This is a test string.";System.out.println(str.contains("test")); // 判断是否包含子串: true
System.out.println(str.startsWith("This")); // 判断是否以指定前缀开头: true
System.out.println(str.endsWith("ing.")); // 判断是否以指定后缀结尾: true
System.out.println(str.substring(5)); // 从索引 5 开始截取到末尾: "is a test string."
System.out.println(str.substring(5, 7)); // 截取 [5, 7) 区间: "is"
5. 转换与替换
String str = " Hello World ";// 1. trim() : 去除首尾空格
System.out.println(str.trim()); // "Hello World"// 2. toUpperCase() / toLowerCase() : 大小写转换
System.out.println(str.toUpperCase()); // " HELLO WORLD "
System.out.println(str.toLowerCase()); // " hello world "// 3. replace() : 替换字符或子串
// 注意:String 不可变,replace() 返回一个新字符串
String newStr = str.replace('l', 'p');
System.out.println(newStr); // " Heppo Worpd "
System.out.println(str.replace("World", "Java")); // " Hello Java "
6. 分割与连接
String str = "apple,banana,orange,grape";// 1. split() : 分割字符串,返回一个字符串数组
String[] fruits = str.split(",");
// fruits: ["apple", "banana", "orange", "grape"]
System.out.println(Arrays.toString(fruits));// 2. join() : 连接字符串 (静态方法)
String result = String.join("-", "apple", "banana", "orange");
// result: "apple-banana-orange"
System.out.println(result);
三、StringBuilder
/ StringBuffer
的常用操作
它们的方法几乎完全一样,区别在于线程安全。这里以 StringBuilder
为例。
1. 创建对象
StringBuilder sb = new StringBuilder(); // 默认容量 (16)
StringBuilder sb2 = new StringBuilder("Hello"); // 初始内容
2. 修改字符串(核心功能)
StringBuilder sb = new StringBuilder("Hello");// 1. append() : 追加内容
sb.append(" World");
System.out.println(sb); // "Hello World"// 2. insert() : 在指定位置插入内容
sb.insert(5, ","); // 在索引 5 的位置插入 ","
System.out.println(sb); // "Hello, World"// 3. delete() : 删除指定区间的内容
sb.delete(5, 7); // 删除 [5, 7) 区间,即删除 ", "
System.out.println(sb); // "HelloWorld"// 4. replace() : 替换指定区间的内容
sb.replace(5, 10, " Java"); // 替换 [5, 10) 区间为 " Java"
System.out.println(sb); // "Hello Java"// 5. reverse() : 反转字符串
sb.reverse();
System.out.println(sb); // "avaJ olleH"// 6. toString() : 转换为 String 对象
String finalString = sb.toString();
System.out.println(finalString); // "avaJ olleH"
四、性能对比:+
拼接 vs StringBuilder
在循环中频繁使用 +
拼接字符串是 Java 新手常见的性能陷阱。
1.错误示例:使用 +
拼接
String result = "";
for (int i = 0; i < 10000; i++) {result = result + i; // 每次循环都会创建一个新的 String 对象,性能极差!
}
2.正确示例:使用 StringBuilder
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10000; i++) {sb.append(i); // 在同一个对象上追加,性能极高!
}
String result = sb.toString();
原因分析:
result + i
的过程实际上是:new StringBuilder().append(result).append(i).toString()
。每次循环都会创建一个StringBuilder
和一个新的String
对象,导致大量内存浪费和 GC(垃圾回收)压力。StringBuilder
的append
方法是在一个预先分配好空间的字符数组上进行操作,避免了频繁创建新对象的开销。