Java 字符串(String / StringBuilder)
字符串是编程中最常用的数据类型之一。Java 提供了 String、StringBuilder 和 StringBuffer 三个字符串类。理解字符串的特性和使用方法是处理文本数据的基础。
String 类与不可变性
String 的不可变性
String 是不可变的(immutable),一旦创建就不能修改。
String str = "Hello";
str = str + " World"; // 不是修改原字符串,而是创建新字符串
原理:
- String 对象创建后,其内容不能改变
- 每次"修改"实际上创建了新的 String 对象
- 原对象如果没有引用,会被垃圾回收
String s1 = "Hello";
String s2 = s1; // s2 和 s1 指向同一个对象
s1 = s1 + " World"; // s1 指向新对象,s2 仍然指向 "Hello"
System.out.println(s1); // "Hello World"
System.out.println(s2); // "Hello"
为什么 String 是不可变的
- 安全性:防止意外修改
- 线程安全:多个线程可以安全共享
- 缓存优化:字符串常量池
- 哈希码缓存:hashCode 可以缓存
字符串创建方式
1. 字面量方式(推荐)
String str = "Hello"; // 使用字符串常量池
2. new 关键字
String str = new String("Hello"); // 创建新对象,不使用常量池
3. 字符串常量池
String s1 = "Hello";
String s2 = "Hello";
String s3 = new String("Hello");
System.out.println(s1 == s2); // true(同一个对象,常量池)
System.out.println(s1 == s3); // false(不同对象)
System.out.println(s1.equals(s3)); // true(内容相同)
字符串常量池:
- 相同字面量的字符串共享同一个对象
- 节省内存
- 使用
==比较引用,equals()比较内容
StringBuilder / StringBuffer 使用
StringBuilder
可变字符串,用于频繁修改字符串的场景。
StringBuilder sb = new StringBuilder();
sb.append("Hello");
sb.append(" ");
sb.append("World");
String result = sb.toString(); // "Hello World"
特点:
- 可变:可以修改内容
- 非线程安全:单线程使用,性能更好
- 高效:适合频繁修改
StringBuffer
可变字符串,线程安全版本。
StringBuffer sb = new StringBuffer();
sb.append("Hello");
sb.append(" ");
sb.append("World");
String result = sb.toString(); // "Hello World"
特点:
- 可变:可以修改内容
- 线程安全:多线程使用
- 性能较低:因为同步开销
StringBuilder vs StringBuffer
| 特性 | StringBuilder | StringBuffer |
|---|---|---|
| 线程安全 | 否 | 是 |
| 性能 | 更高 | 较低 |
| 使用场景 | 单线程 | 多线程 |
选择建议:
- 单线程:使用 StringBuilder
- 多线程:使用 StringBuffer
常用方法
append:追加
StringBuilder sb = new StringBuilder();
sb.append("Hello");
sb.append(" ");
sb.append("World");
sb.append(123); // 可以追加各种类型
insert:插入
StringBuilder sb = new StringBuilder("Hello");
sb.insert(5, " World"); // "Hello World"
delete:删除
StringBuilder sb = new StringBuilder("Hello World");
sb.delete(5, 11); // "Hello"(删除索引 5 到 10)
replace:替换
StringBuilder sb = new StringBuilder("Hello World");
sb.replace(0, 5, "Hi"); // "Hi World"
reverse:反转
StringBuilder sb = new StringBuilder("Hello");
sb.reverse(); // "olleH"
String 常用方法
String 的常用方法包括 length()、substring()、charAt()、replace() 等,下面逐一介绍。
1. 长度和空值检查
String str = "Hello";
// 获取长度
int length = str.length(); // 5
// 检查是否为空
boolean isEmpty = str.isEmpty(); // false
boolean isBlank = str.isBlank(); // false(Java 11+)
// 检查是否为 null 或空
if (str != null && !str.isEmpty()) {
// 处理字符串
}
2. 字符访问
String str = "Hello";
// 获取指定位置的字符
char ch = str.charAt(0); // 'H'
// 转换为字符数组
char[] chars = str.toCharArray(); // ['H', 'e', 'l', 'l', 'o']
3. 子字符串
String str = "Hello World";
// substring:提取子字符串
String sub1 = str.substring(6); // "World"(从索引 6 到末尾)
String sub2 = str.substring(0, 5); // "Hello"(从索引 0 到 4)
// 注意:substring 的第二个参数是结束索引(不包含)
4. 查找
String str = "Hello World";
// indexOf:查找字符或字符串的位置
int index1 = str.indexOf('o'); // 4(第一 个 'o')
int index2 = str.indexOf('o', 5); // 7(从索引 5 开始查找)
int index3 = str.indexOf("World"); // 6
// lastIndexOf:从后往前查找
int lastIndex = str.lastIndexOf('o'); // 7
// contains:是否包含
boolean contains = str.contains("World"); // true
// startsWith / endsWith:是否以指定字符串开头/结尾
boolean starts = str.startsWith("Hello"); // true
boolean ends = str.endsWith("World"); // true
5. 替换
String str = "Hello World";
// replace:替换字符 或字符串
String replaced1 = str.replace('l', 'L'); // "HeLLo WorLd"
String replaced2 = str.replace("World", "Java"); // "Hello Java"
// replaceAll:使用正则表达式替换
String replaced3 = str.replaceAll("\\s", "-"); // "Hello-World"(替换空格)
// replaceFirst:替换第一个匹配
String replaced4 = str.replaceFirst("l", "L"); // "HeLlo World"
6. 大小写转换
String str = "Hello World";
// 转大写
String upper = str.toUpperCase(); // "HELLO WORLD"
// 转小写
String lower = str.toLowerCase(); // "hello world"
7. 去除空白
String str = " Hello World ";
// trim:去除首尾空白
String trimmed = str.trim(); // "Hello World"
// strip:去除首尾空白(Java 11+,支持 Unicode)
String stripped = str.strip(); // "Hello World"
// stripLeading / stripTrailing:去除开头/结尾空白
String leading = str.stripLeading(); // "Hello World "
String trailing = str.stripTrailing(); // " Hello World"
8. 分割
String str = "apple,banana,orange";
// split:分割字符串
String[] fruits = str.split(","); // ["apple", "banana", "orange"]
// 限制分割次数
String[] parts = str.split(",", 2); // ["apple", "banana,orange"]
9. 连接
// join:连接字符串数组(Java 8+)
String[] arr = {"apple", "banana", "orange"};
String joined = String.join(", ", arr); // "apple, banana, orange"
10. 比较
String s1 = "Hello";
String s2 = "hello";
// equals:比较内容(区分大小写)
boolean equal1 = s1.equals(s2); // false
// equalsIgnoreCase:比较内容(不区分大小写)
boolean equal2 = s1.equalsIgnoreCase(s2); // true
// compareTo:按字典序比较
int result = s1.compareTo(s2); // 负数(s1 < s2)
// compareToIgnoreCase:不区分大小写比较
int result2 = s1.compareToIgnoreCase(s2); // 0(相等)