StringBuilder常用API
# StringBuilder 和 StringBuffer
# 1. 概述
StringBuilder
和 StringBuffer
是 Java 中用于处理可变字符串的类,它们提供了丰富的字符串操作方法,如追加、插入、删除、替换等。在实际开发中,StringBuilder
更适合单线程环境,而 StringBuffer
因为是线程安全的,适用于多线程环境。
# 2. 构造方法详解
StringBuilder()
: 构造一个空的StringBuilder
对象。StringBuilder(CharSequence seq)
: 使用指定的字符序列初始化StringBuilder
对象。StringBuilder(int capacity)
: 构造一个具有指定初始容量的StringBuilder
对象。StringBuffer()
: 构造一个空的StringBuffer
对象。StringBuffer(CharSequence seq)
: 使用指定的字符序列初始化StringBuffer
对象。StringBuffer(int capacity)
: 构造一个具有指定初始容量的StringBuffer
对象。
基本使用示例:
public class StringBuilderAndBufferDemo {
public static void main(String[] args) {
// 创建空的 StringBuilder 对象
StringBuilder sb1 = new StringBuilder();
// 使用指定的字符序列初始化 StringBuilder 对象
CharSequence sequence = "Hello";
StringBuilder sb2 = new StringBuilder(sequence);
// 指定初始容量的 StringBuilder 对象
StringBuilder sb3 = new StringBuilder(50);
System.out.println("sb1 初始容量: " + sb1.capacity());
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
实际开发场景:
在处理大规模字符串拼接时,如构建长 SQL 查询语句或动态生成 HTML 片段,可以通过指定初始容量来优化性能,减少内存重新分配的次数。
# 3. 容量和长度管理
int length()
: 返回当前字符串的长度。int capacity()
: 返回当前StringBuilder
或StringBuffer
的容量。void ensureCapacity(int minimumCapacity)
: 确保容量至少为指定值。void trimToSize()
: 将容量调整为当前字符串的长度。
基本使用示例:
public class CapacityAndLengthDemo {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder("Hello, World!");
// 获取当前字符串长度
int length = sb.length();
System.out.println("字符串长度: " + length); // 输出 13
// 获取当前容量
int capacity = sb.capacity();
System.out.println("初始容量: " + capacity); // 输出 29 (13 + 16)
// 确保容量至少为 50
sb.ensureCapacity(50);
System.out.println("扩展后的容量: " + sb.capacity()); // 输出 50
// 将容量调整为当前字符串长度
sb.trimToSize();
System.out.println("调整后的容量: " + sb.capacity()); // 输出 13
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
实际开发场景:
当处理大量字符串拼接时,通过 ensureCapacity
预先扩容可以避免内存频繁扩展,提升性能;trimToSize
则用于优化内存占用。
# 4. 字符串的追加和插入操作
StringBuilder append(String str)
: 将字符串追加到末尾。StringBuilder insert(int offset, String str)
: 在指定位置插入字符串。StringBuffer append(String str)
: 同样追加字符串到末尾(线程安全)。StringBuffer insert(int offset, String str)
: 在指定位置插入字符串(线程安全)。
基本使用示例:
public class AppendAndInsertDemo {
public static void main(String[] args) {
// StringBuilder 追加和插入操作
StringBuilder sb = new StringBuilder("Hello");
sb.append(", World!");
System.out.println("追加后的结果: " + sb); // 输出 "Hello, World!"
sb.insert(5, " Java");
System.out.println("插入后的结果: " + sb); // 输出 "Hello Java, World!"
// StringBuffer 追加和插入操作(线程安全)
StringBuffer buffer = new StringBuffer("Welcome");
buffer.append(" to Java.");
System.out.println("StringBuffer 追加后的结果: " + buffer); // 输出 "Welcome to Java."
buffer.insert(7, " Learning");
System.out.println("StringBuffer 插入后的结果: " + buffer); // 输出 "Welcome Learning to Java."
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
实际开发场景:
通常用于动态生成复杂文本内容,如报告生成、日志格式化等场景。
# 5. 删除和替换字符串
StringBuilder delete(int start, int end)
: 删除从start
到end
(不包括)的字符。StringBuilder deleteCharAt(int index)
: 删除指定索引处的字符。StringBuilder replace(int start, int end, String str)
: 用指定字符串替换从start
到end
的字符。StringBuffer
对应的操作类似,支持线程安全。
基本使用示例:
public class DeleteAndReplaceDemo {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder("Hello, World!");
// 删除索引 5 到 10 的字符
sb.delete(5, 10);
System.out.println("删除后的结果: " + sb); // 输出 "Hello World!"
// 删除索引 5 处的字符
sb.deleteCharAt(5);
System.out.println("删除指定索引后的结果: " + sb); // 输出 "HelloWorld!"
// 替换索引 6 到 11 的字符
sb.replace(6, 11, "Java");
System.out.println("替换后的结果: " + sb); // 输出 "Hello Java!"
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
实际开发场景:
适用于清除敏感信息或替换特定内容,如日志信息中隐藏用户数据。
# 6. 截取子串操作
String substring(int start)
: 返回从start
开始的子字符串。String substring(int start, int end)
: 返回从start
到end
的子字符串。
基本使用示例:
public class SubstringDemo {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder("Hello, World!");
// 获取从索引 7 开始的子串
String subStr1 = sb.substring(7);
System.out.println("子串1: " + subStr1); // 输出 "World!"
// 获取索引 0 到 5 的子串
String subStr2 = sb.substring(0, 5);
System.out.println("子串2: " + subStr2); // 输出 "Hello"
}
}
2
3
4
5
6
7
8
9
10
11
12
13
实际开发场景:
用于提取字符串中的特定部分,如解析 URL、提取参数或路径。
# 7. 字符和索引操作
void setCharAt(int index, char ch)
: 设置指定索引处的字符。char charAt(int index)
: 获取指定索引处的字符。void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)
: 将字符从源字符串复制到目标数组中。
基本使用示例:
public class CharAndIndexDemo {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder("Hello, Java!");
// 设置索引 7 处的字符
sb.setCharAt(7, 'W');
System.out.println("修改字符后的结果: " + sb); // 输出 "Hello, Wava!"
// 获取索引 6 处的字符
char character = sb.charAt(6);
System.out.println("索引 6 处的字符: " + character); // 输出 ' '
// 复制字符到数组
char[] destination = new char[5];
sb.getChars(7, 12, destination, 0);
System.out.print("复制的字符: ");
for (char c : destination) {
System.out.print(c); // 输出 "Wava!"
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
实际开发场景:
在字符处理、文本解析等场景中,通过索引访问和修改字符可高效完成特定任务。
# 8. 查找字符串索引
int indexOf(String str)
: 查找指定字符串第一次出现的位置,未找到则返回 -1。int indexOf(String str, int fromIndex)
: 从指定位置开始查找,返回第一次出现的位置。int lastIndexOf(String str)
: 查找指定字符串最后一次出现的位置。int lastIndexOf(String str, int fromIndex)
: 从指定位置向前查找,返回最后一次出现的位置。
基本使用示例:
public class IndexOfDemo {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder("Hello, World!");
// 查找 "World" 第一次出现的位置
int index1 = sb.indexOf("World");
System.out.println("World 第一次出现的位置: " + index1); // 输出 7
// 从索引 8 开始查找 "World"
int index2 = sb.indexOf("World", 8);
System.out.println("从索引 8 开始查找 World: " + index2); // 输出 -1 (未找到)
// 查找字符 'l' 的最后一次出现位置
int lastIndex = sb.lastIndexOf("l");
System.out.println("字符 'l' 最后一次出现的位置: " + lastIndex); // 输出 10
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
实际开发场景:
在日志分析或文件解析中,可用于快速定位关键信息的位置。
# 9. 字符串反转与转换
void reverse()
: 反转StringBuilder
中的字符序列。String toString()
: 将StringBuilder
转换为不可变的字符串对象。
基本使用示例:
public class ReverseAndToStringDemo {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder("Hello");
// 反转字符串
sb.reverse();
System.out.println("反转后的结果: " + sb); // 输出 "olleH"
// 将 StringBuilder 转换为字符串
String str = sb.toString();
System.out.println("转换后的字符串: " + str); // 输出 "olleH"
}
}
2
3
4
5
6
7
8
9
10
11
12
13
实际开发场景:
反转字符串常用于算法题中,如判断回文字符串;toString
常用于最终输出或返回操作,将可变字符串转换为不可变对象。
# 10. 刷题中常用的 StringBuilder
在 LeetCode 刷题中,StringBuilder
是一个高效处理字符串的工具,以下方法经常被用到:
append()
:这是最常用的方法,能够高效拼接字符或字符串。特别是在处理大量字符串拼接时,StringBuilder
的append
比直接使用字符串拼接(如+
运算符)更加高效,避免了创建大量的中间对象。reverse()
:在需要反转字符串时非常方便,直接调用此方法即可快速实现,避免了手动循环操作。deleteCharAt()
:用于在处理栈模拟时删除最后一个字符。例如,在括号匹配问题中,deleteCharAt
可以模拟出栈操作。setCharAt()
:当需要修改特定位置的字符时,这个方法比创建新的字符串更高效。toString()
:最终将StringBuilder
转换为不可变的字符串进行输出,是返回结果的常用方式。
# 1. 有效的括号
题目要求判断给定的括号序列是否有效。有效的括号满足:每个左括号都有对应的右括号,并且匹配顺序正确。
代码示例:
public boolean isValid(String s) {
// 使用 StringBuilder 模拟栈操作
StringBuilder stack = new StringBuilder();
for (char c : s.toCharArray()) {
// 遇到左括号,加入栈中
if (c == '(' || c == '{' || c == '[') {
stack.append(c);
} else {
// 遇到右括号,先检查栈是否为空
if (stack.length() == 0) return false;
// 获取栈顶元素(最后一个字符)
char top = stack.charAt(stack.length() - 1);
// 判断是否匹配,匹配则弹出栈顶元素
if ((c == ')' && top == '(') || (c == '}' && top == '{') || (c == ']' && top == '[')) {
stack.deleteCharAt(stack.length() - 1); // 模拟出栈
} else {
return false; // 不匹配则直接返回 false
}
}
}
// 最终栈为空则匹配成功
return stack.length() == 0;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
分析:
- 该题目利用
StringBuilder
来模拟栈结构,通过append
和deleteCharAt
来实现入栈和出栈操作。 - 相比直接使用栈(
Stack
类),StringBuilder
在字符串操作上更高效。
# 2. 反转字符串中的单词
题目要求将字符串中的单词顺序反转。例如,输入 "the sky is blue"
,输出 "blue is sky the"
。
代码示例:
public String reverseWords(String s) {
// 去掉字符串两端的空格,并按一个或多个空格分割
String[] words = s.trim().split("\\s+");
StringBuilder sb = new StringBuilder();
// 反向遍历数组,构建结果字符串
for (int i = words.length - 1; i >= 0; i--) {
sb.append(words[i]);
if (i > 0) {
sb.append(" "); // 每个单词之间添加空格
}
}
// 将 StringBuilder 转为字符串返回
return sb.toString();
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
分析:
reverseWords
通过StringBuilder
高效地拼接反转后的单词序列。StringBuilder
的append
方法能够避免频繁创建新的字符串对象,从而提高性能。
# 3. 字符串压缩
题目要求将字符串进行压缩,如输入 "aaabbccc"
输出 "a3b2c3"
。
代码示例:
public String compressString(String s) {
if (s == null || s.length() == 0) return s;
StringBuilder sb = new StringBuilder();
int count = 1;
// 遍历字符串进行压缩处理
for (int i = 1; i < s.length(); i++) {
if (s.charAt(i) == s.charAt(i - 1)) {
count++; // 相同字符计数增加
} else {
sb.append(s.charAt(i - 1)).append(count); // 添加字符和计数
count = 1; // 重置计数器
}
}
// 添加最后一组字符和计数
sb.append(s.charAt(s.length() - 1)).append(count);
return sb.toString();
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
分析:
compressString
通过遍历字符串并使用StringBuilder
拼接压缩后的结果。- 使用
append
方法能够有效减少创建中间字符串对象,提高效率。
# 4. 回文字符串
题目要求判断一个字符串是否是回文字符串,即正序和倒序一致。
代码示例:
public boolean isPalindrome(String s) {
StringBuilder filtered = new StringBuilder();
// 过滤出字母和数字字符,并转换为小写
for (char c : s.toCharArray()) {
if (Character.isLetterOrDigit(c)) {
filtered.append(Character.toLowerCase(c));
}
}
// 获取反转后的字符串
String reversed = filtered.reverse().toString();
// 判断正序与反序是否一致
return filtered.reverse().toString().equals(reversed);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
分析:
- 该题利用
StringBuilder
的reverse
方法实现字符串反转,并通过toString
进行比较。 StringBuilder
的可变性和方法的多样性,使得该题的实现更加简洁和高效。