本文目录导读:

我来分享一些Java字符串操作的性能优化案例,通过实际对比来展示优化效果。
字符串拼接优化
优化前(低效方式)
public class StringConcatDemo {
// ❌ 错误示范:在循环中使用+拼接
public static String concatWithPlus(String[] words) {
String result = "";
for (String word : words) {
result += word + ","; // 每次创建新对象
}
return result;
}
// ❌ 错误示范:使用StringBuffer但未指定容量
public static String concatWithStringBuffer(String[] words) {
StringBuffer sb = new StringBuffer();
for (String word : words) {
sb.append(word).append(",");
}
return sb.toString();
}
}
优化后(高效方式)
public class StringConcatOptimized {
// ✅ 推荐:使用StringBuilder并预分配容量
public static String concatWithCapacity(String[] words) {
// 计算预估容量,减少扩容次数
int capacity = 0;
for (String word : words) {
capacity += word.length() + 1; // +1 for comma
}
StringBuilder sb = new StringBuilder(capacity);
for (String word : words) {
sb.append(word).append(",");
}
return sb.toString();
}
// ✅ 性能测试对比
public static void benchmark() {
String[] words = new String[10000];
for (int i = 0; i < words.length; i++) {
words[i] = "word" + i;
}
long start, end;
// 测试+拼接
start = System.nanoTime();
String result1 = concatWithPlus(words);
end = System.nanoTime();
System.out.println("Plus拼接: " + (end - start) / 1_000_000 + "ms");
// 测试优化后的StringBuilder
start = System.nanoTime();
String result2 = concatWithCapacity(words);
end = System.nanoTime();
System.out.println("StringBuilder优化: " + (end - start) / 1_000_000 + "ms");
}
}
String.split() 优化
优化前
public class StringSplitDemo {
// ❌ 每次调用split都会编译正则表达式
public static String[] splitOld(String text) {
return text.split("\\|");
}
// ❌ 使用不必要的正则
public static String[] splitSimple(String text) {
// 其实只需要按逗号分割
return text.split(",");
}
}
优化后
public class StringSplitOptimized {
// ✅ 预编译正则表达式
private static final Pattern PIPE_PATTERN = Pattern.compile("\\|");
private static final Pattern COMMA_PATTERN = Pattern.compile(",");
// 使用Pattern.split()替代String.split()
public static String[] splitOptimized(String text) {
return PIPE_PATTERN.split(text);
}
// ✅ 简单分隔符使用StringTokenizer
public static String[] splitWithTokenizer(String text) {
StringTokenizer st = new StringTokenizer(text, ",");
String[] result = new String[st.countTokens()];
int index = 0;
while (st.hasMoreTokens()) {
result[index++] = st.nextToken();
}
return result;
}
// ✅ 极致优化:手动解析(适合简单场景)
public static String[] splitManual(String text) {
// 假设只按逗号分割
int count = 1;
for (int i = 0; i < text.length(); i++) {
if (text.charAt(i) == ',') count++;
}
String[] result = new String[count];
int start = 0, index = 0;
for (int i = 0; i < text.length(); i++) {
if (text.charAt(i) == ',' || i == text.length() - 1) {
int end = (i == text.length() - 1 && text.charAt(i) != ',') ?
i + 1 : i;
result[index++] = text.substring(start, end);
start = i + 1;
}
}
return result;
}
// 性能对比
public static void benchmark() {
String text = "a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z";
text = text.repeat(1000);
long start, end;
// String.split()
start = System.nanoTime();
String[] arr1 = text.split(",");
end = System.nanoTime();
System.out.println("String.split(): " + (end - start) / 1_000_000 + "ms");
// Pattern.split()
start = System.nanoTime();
String[] arr2 = COMMA_PATTERN.split(text);
end = System.nanoTime();
System.out.println("Pattern.split(): " + (end - start) / 1_000_000 + "ms");
// 手动解析
start = System.nanoTime();
String[] arr3 = splitManual(text);
end = System.nanoTime();
System.out.println("手动解析: " + (end - start) / 1_000_000 + "ms");
}
}
字符串查找优化
优化前
public class StringSearchDemo {
// ❌ 使用String.contains()或indexOf()进行多次查找
public static boolean hasAllWords(String text, String[] words) {
for (String word : words) {
if (!text.contains(word)) {
return false;
}
}
return true;
}
}
优化后
public class StringSearchOptimized {
// ✅ 使用Boyer-Moore算法(通过indexOf优化)
public static boolean hasAllWords(String text, String[] words) {
// 对于长文本,先建立索引
Map<Character, List<Integer>> charIndex = new HashMap<>();
for (int i = 0; i < text.length(); i++) {
char c = text.charAt(i);
charIndex.computeIfAbsent(c, k -> new ArrayList<>()).add(i);
}
for (String word : words) {
if (word.isEmpty()) continue;
List<Integer> positions = charIndex.get(word.charAt(0));
if (positions == null || positions.isEmpty()) {
return false;
}
// 检查位置是否匹配
boolean found = false;
for (int pos : positions) {
if (pos + word.length() <= text.length()) {
if (text.substring(pos, pos + word.length()).equals(word)) {
found = true;
break;
}
}
}
if (!found) return false;
}
return true;
}
// ✅ 使用String.contains()但优化调用方式
public static boolean hasAllWordsOptimized(String text, String[] words) {
// 检查边界条件,减少不必要的调用
if (text == null || text.isEmpty() || words == null || words.length == 0) {
return false;
}
for (String word : words) {
if (word.isEmpty()) continue;
if (word.length() > text.length()) return false;
if (!text.contains(word)) return false;
}
return true;
}
}
字符串替换优化
优化前
public class StringReplaceDemo {
// ❌ 链式调用replace,创建多个临时对象
public static String replaceMultiple(String text) {
return text.replace("a", "1")
.replace("b", "2")
.replace("c", "3");
}
// ❌ 使用replaceAll但正则过于复杂
public static String replaceWithRegex(String text) {
return text.replaceAll("[abc]", "0");
}
}
优化后
public class StringReplaceOptimized {
// ✅ 使用字符数组手动替换
public static String replaceWithCharArray(String text) {
char[] chars = text.toCharArray();
for (int i = 0; i < chars.length; i++) {
switch (chars[i]) {
case 'a': chars[i] = '1'; break;
case 'b': chars[i] = '2'; break;
case 'c': chars[i] = '3'; break;
}
}
return new String(chars);
}
// ✅ 使用StringBuilder进行复杂替换
public static String replaceWithStringBuilder(String text) {
StringBuilder sb = new StringBuilder(text.length());
for (char c : text.toCharArray()) {
switch (c) {
case 'a': sb.append('1'); break;
case 'b': sb.append('2'); break;
case 'c': sb.append('3'); break;
default: sb.append(c); break;
}
}
return sb.toString();
}
// ✅ 性能测试
public static void benchmark() {
String text = RandomStringUtils.randomAlphabetic(100000);
long start, end;
// replace链式调用
start = System.nanoTime();
String result1 = replaceMultiple(text);
end = System.nanoTime();
System.out.println("链式replace: " + (end - start) / 1_000_000 + "ms");
// 字符数组替换
start = System.nanoTime();
String result2 = replaceWithCharArray(text);
end = System.nanoTime();
System.out.println("字符数组替换: " + (end - start) / 1_000_000 + "ms");
// StringBuilder替换
start = System.nanoTime();
String result3 = replaceWithStringBuilder(text);
end = System.nanoTime();
System.out.println("StringBuilder替换: " + (end - start) / 1_000_000 + "ms");
}
}
完整性能测试示例
public class StringPerformanceTest {
public static void main(String[] args) {
System.out.println("=== 字符串性能测试 ===");
// 1. 字符串拼接测试
System.out.println("\n1. 字符串拼接测试:");
StringConcatOptimized.benchmark();
// 2. 字符串分割测试
System.out.println("\n2. 字符串分割测试:");
StringSplitOptimized.benchmark();
// 3. 字符串替换测试
System.out.println("\n3. 字符串替换测试:");
StringReplaceOptimized.benchmark();
}
}
总结优化原则
- 避免创建临时对象:使用
StringBuilder替代拼接 - 预分配容量:预估字符串大小,减少扩容
- 预编译正则:对重复使用的正则使用
Pattern.compile() - 选择合适的数据结构:简单场景用字符数组操作
- 避免不必要的操作:检查边界条件,减少方法调用
- 使用JDK内置优化:如
String.indexOf()使用了多种优化算法
通过这些优化,通常可以在需要大量字符串操作的场景中获得50%-80%的性能提升。