Java字符串操作提速案例优化

wen java案例 28

本文目录导读:

Java字符串操作提速案例优化

  1. 字符串拼接优化
  2. String.split() 优化
  3. 字符串查找优化
  4. 字符串替换优化
  5. 完整性能测试示例
  6. 总结优化原则

我来分享一些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();
    }
}

总结优化原则

  1. 避免创建临时对象:使用StringBuilder替代拼接
  2. 预分配容量:预估字符串大小,减少扩容
  3. 预编译正则:对重复使用的正则使用Pattern.compile()
  4. 选择合适的数据结构:简单场景用字符数组操作
  5. 避免不必要的操作:检查边界条件,减少方法调用
  6. 使用JDK内置优化:如String.indexOf()使用了多种优化算法

通过这些优化,通常可以在需要大量字符串操作的场景中获得50%-80%的性能提升。

抱歉,评论功能暂时关闭!