10.1 String类详解

10.1.1 String类基础

String是Java中最常用的类之一,用于表示字符序列。String对象是不可变的(immutable),这意味着一旦创建就不能修改。

import java.util.*;
import java.util.regex.*;
import java.text.*;
import java.nio.charset.*;

/**
 * String类详细演示
 */
public class StringBasicsDemo {
    public static void main(String[] args) {
        System.out.println("=== String类详细演示 ===");
        
        demonstrateStringCreation();
        demonstrateStringImmutability();
        demonstrateStringComparison();
        demonstrateStringMethods();
        demonstrateStringPool();
    }
    
    public static void demonstrateStringCreation() {
        System.out.println("\n--- String创建方式 ---");
        
        // 1. 字面量创建
        System.out.println("\n1. 字面量创建:");
        String str1 = "Hello, World!";
        String str2 = "Hello, World!";
        System.out.println("str1: " + str1);
        System.out.println("str2: " + str2);
        System.out.println("str1 == str2: " + (str1 == str2)); // true,指向同一个对象
        
        // 2. new关键字创建
        System.out.println("\n2. new关键字创建:");
        String str3 = new String("Hello, World!");
        String str4 = new String("Hello, World!");
        System.out.println("str3: " + str3);
        System.out.println("str4: " + str4);
        System.out.println("str3 == str4: " + (str3 == str4)); // false,不同对象
        System.out.println("str1 == str3: " + (str1 == str3)); // false
        
        // 3. 从字符数组创建
        System.out.println("\n3. 从字符数组创建:");
        char[] charArray = {'H', 'e', 'l', 'l', 'o'};
        String str5 = new String(charArray);
        String str6 = new String(charArray, 1, 3); // 从索引1开始,长度为3
        System.out.println("从完整字符数组: " + str5);
        System.out.println("从部分字符数组: " + str6);
        
        // 4. 从字节数组创建
        System.out.println("\n4. 从字节数组创建:");
        byte[] byteArray = {72, 101, 108, 108, 111}; // "Hello"的ASCII码
        String str7 = new String(byteArray);
        String str8 = new String(byteArray, StandardCharsets.UTF_8);
        System.out.println("从字节数组(默认编码): " + str7);
        System.out.println("从字节数组(UTF-8编码): " + str8);
        
        // 5. 使用StringBuilder转换
        System.out.println("\n5. 使用StringBuilder转换:");
        StringBuilder sb = new StringBuilder("Hello");
        sb.append(", World!");
        String str9 = sb.toString();
        System.out.println("从StringBuilder: " + str9);
        
        // 6. 空字符串和null
        System.out.println("\n6. 空字符串和null:");
        String emptyString = "";
        String nullString = null;
        String blankString = "   ";
        
        System.out.println("空字符串长度: " + emptyString.length());
        System.out.println("空字符串是否为空: " + emptyString.isEmpty());
        System.out.println("空白字符串是否为空: " + blankString.isEmpty());
        System.out.println("空白字符串是否为空白: " + blankString.isBlank()); // Java 11+
        
        // 注意:nullString.length() 会抛出NullPointerException
        System.out.println("null字符串: " + nullString);
    }
    
    public static void demonstrateStringImmutability() {
        System.out.println("\n--- String不可变性 ---");
        
        System.out.println("\n1. String不可变性演示:");
        String original = "Hello";
        String modified = original.concat(", World!");
        
        System.out.println("原始字符串: " + original);
        System.out.println("修改后字符串: " + modified);
        System.out.println("原始字符串是否改变: " + original.equals("Hello"));
        
        // 2. 字符串操作创建新对象
        System.out.println("\n2. 字符串操作创建新对象:");
        String str = "Java";
        System.out.println("原始字符串: " + str);
        System.out.println("原始字符串hashCode: " + str.hashCode());
        
        String upperStr = str.toUpperCase();
        System.out.println("转大写后: " + upperStr);
        System.out.println("转大写后hashCode: " + upperStr.hashCode());
        
        String replacedStr = str.replace('a', 'o');
        System.out.println("替换字符后: " + replacedStr);
        System.out.println("替换字符后hashCode: " + replacedStr.hashCode());
        
        // 3. 不可变性的优势
        System.out.println("\n3. 不可变性的优势:");
        System.out.println("- 线程安全:多个线程可以安全地访问同一个String对象");
        System.out.println("- 缓存hashCode:String的hashCode只计算一次");
        System.out.println("- 字符串池:相同内容的字符串可以共享内存");
        System.out.println("- 安全性:字符串内容不会被意外修改");
        
        // 4. 性能考虑
        System.out.println("\n4. 性能考虑:");
        demonstrateStringConcatenationPerformance();
    }
    
    private static void demonstrateStringConcatenationPerformance() {
        System.out.println("\n字符串拼接性能对比:");
        
        int iterations = 1000;
        
        // 使用+操作符(不推荐在循环中使用)
        long startTime = System.nanoTime();
        String result1 = "";
        for (int i = 0; i < iterations; i++) {
            result1 += "a";
        }
        long stringConcatTime = System.nanoTime() - startTime;
        
        // 使用StringBuilder(推荐)
        startTime = System.nanoTime();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < iterations; i++) {
            sb.append("a");
        }
        String result2 = sb.toString();
        long stringBuilderTime = System.nanoTime() - startTime;
        
        System.out.println("String +操作符: " + stringConcatTime / 1_000_000 + "ms");
        System.out.println("StringBuilder: " + stringBuilderTime / 1_000_000 + "ms");
        System.out.println("StringBuilder比+操作符快: " + 
            (stringConcatTime / (double) stringBuilderTime) + "倍");
    }
    
    public static void demonstrateStringComparison() {
        System.out.println("\n--- 字符串比较 ---");
        
        String str1 = "Hello";
        String str2 = "Hello";
        String str3 = new String("Hello");
        String str4 = "hello";
        String str5 = null;
        
        // 1. == 比较(引用比较)
        System.out.println("\n1. == 比较(引用比较):");
        System.out.println("str1 == str2: " + (str1 == str2)); // true
        System.out.println("str1 == str3: " + (str1 == str3)); // false
        
        // 2. equals() 比较(内容比较)
        System.out.println("\n2. equals() 比较(内容比较):");
        System.out.println("str1.equals(str2): " + str1.equals(str2)); // true
        System.out.println("str1.equals(str3): " + str1.equals(str3)); // true
        System.out.println("str1.equals(str4): " + str1.equals(str4)); // false
        System.out.println("str1.equals(str5): " + str1.equals(str5)); // false
        
        // 3. equalsIgnoreCase() 比较(忽略大小写)
        System.out.println("\n3. equalsIgnoreCase() 比较(忽略大小写):");
        System.out.println("str1.equalsIgnoreCase(str4): " + str1.equalsIgnoreCase(str4)); // true
        
        // 4. compareTo() 比较(字典序)
        System.out.println("\n4. compareTo() 比较(字典序):");
        System.out.println("str1.compareTo(str2): " + str1.compareTo(str2)); // 0
        System.out.println("str1.compareTo(str4): " + str1.compareTo(str4)); // 负数
        System.out.println("\"Apple\".compareTo(\"Banana\"): " + "Apple".compareTo("Banana")); // 负数
        System.out.println("\"Zebra\".compareTo(\"Apple\"): " + "Zebra".compareTo("Apple")); // 正数
        
        // 5. compareToIgnoreCase() 比较
        System.out.println("\n5. compareToIgnoreCase() 比较:");
        System.out.println("str1.compareToIgnoreCase(str4): " + str1.compareToIgnoreCase(str4)); // 0
        
        // 6. 安全的字符串比较
        System.out.println("\n6. 安全的字符串比较:");
        System.out.println("Objects.equals(str1, str5): " + Objects.equals(str1, str5)); // false
        System.out.println("Objects.equals(str5, str5): " + Objects.equals(str5, str5)); // true
        
        // 避免NullPointerException的方法
        System.out.println("\"Hello\".equals(str5): " + "Hello".equals(str5)); // false,安全
        // str5.equals("Hello") 会抛出NullPointerException
    }
    
    public static void demonstrateStringMethods() {
        System.out.println("\n--- String常用方法 ---");
        
        String text = "  Hello, Java World! Welcome to Programming.  ";
        
        // 1. 长度和字符访问
        System.out.println("\n1. 长度和字符访问:");
        System.out.println("原始字符串: '" + text + "'");
        System.out.println("长度: " + text.length());
        System.out.println("第5个字符: " + text.charAt(5));
        System.out.println("字符数组: " + Arrays.toString(text.toCharArray()));
        
        // 2. 大小写转换
        System.out.println("\n2. 大小写转换:");
        System.out.println("转大写: " + text.toUpperCase());
        System.out.println("转小写: " + text.toLowerCase());
        
        // 3. 去除空白
        System.out.println("\n3. 去除空白:");
        System.out.println("去除首尾空白: '" + text.trim() + "'");
        System.out.println("去除所有空白: '" + text.strip() + "'"); // Java 11+
        System.out.println("去除开头空白: '" + text.stripLeading() + "'"); // Java 11+
        System.out.println("去除结尾空白: '" + text.stripTrailing() + "'"); // Java 11+
        
        // 4. 查找和检查
        System.out.println("\n4. 查找和检查:");
        System.out.println("包含'Java': " + text.contains("Java"));
        System.out.println("以'  Hello'开头: " + text.startsWith("  Hello"));
        System.out.println("以'.'结尾: " + text.endsWith("."));
        System.out.println("'Java'的位置: " + text.indexOf("Java"));
        System.out.println("'o'最后出现位置: " + text.lastIndexOf("o"));
        System.out.println("是否为空: " + text.isEmpty());
        System.out.println("是否为空白: " + text.isBlank()); // Java 11+
        
        // 5. 子字符串
        System.out.println("\n5. 子字符串:");
        System.out.println("从索引7开始: '" + text.substring(7) + "'");
        System.out.println("索引7到12: '" + text.substring(7, 12) + "'");
        
        // 6. 替换
        System.out.println("\n6. 替换:");
        System.out.println("替换'Java'为'Python': " + text.replace("Java", "Python"));
        System.out.println("替换第一个'o'为'0': " + text.replaceFirst("o", "0"));
        System.out.println("替换所有'o'为'0': " + text.replaceAll("o", "0"));
        
        // 7. 分割
        System.out.println("\n7. 分割:");
        String sentence = "apple,banana,orange,grape";
        String[] fruits = sentence.split(",");
        System.out.println("分割结果: " + Arrays.toString(fruits));
        
        String[] limitedSplit = sentence.split(",", 2);
        System.out.println("限制分割数量: " + Arrays.toString(limitedSplit));
        
        // 8. 连接
        System.out.println("\n8. 连接:");
        String joined = String.join(" | ", fruits);
        System.out.println("连接数组: " + joined);
        
        List<String> list = Arrays.asList("Java", "Python", "C++", "JavaScript");
        String joinedList = String.join(", ", list);
        System.out.println("连接列表: " + joinedList);
        
        // 9. 格式化
        System.out.println("\n9. 格式化:");
        String formatted = String.format("姓名: %s, 年龄: %d, 分数: %.2f", "张三", 25, 95.678);
        System.out.println("格式化字符串: " + formatted);
        
        // Java 15+ 文本块
        System.out.println("\n10. 文本块 (Java 15+):");
        String textBlock = """
                           这是一个文本块
                           可以包含多行
                           保持格式
                           """;
        System.out.println("文本块: " + textBlock);
    }
    
    public static void demonstrateStringPool() {
        System.out.println("\n--- 字符串池 ---");
        
        // 1. 字符串池基础
        System.out.println("\n1. 字符串池基础:");
        String str1 = "Hello";
        String str2 = "Hello";
        String str3 = new String("Hello");
        
        System.out.println("str1 == str2: " + (str1 == str2)); // true,来自字符串池
        System.out.println("str1 == str3: " + (str1 == str3)); // false,str3在堆中
        
        // 2. intern()方法
        System.out.println("\n2. intern()方法:");
        String str4 = str3.intern(); // 将str3加入字符串池
        System.out.println("str1 == str4: " + (str1 == str4)); // true
        
        // 3. 字符串池的内存优化
        System.out.println("\n3. 字符串池的内存优化:");
        demonstrateStringPoolMemory();
        
        // 4. 编译时常量
        System.out.println("\n4. 编译时常量:");
        String compile1 = "Hello" + "World"; // 编译时连接
        String compile2 = "HelloWorld";
        System.out.println("编译时常量相等: " + (compile1 == compile2)); // true
        
        String runtime1 = "Hello";
        String runtime2 = runtime1 + "World"; // 运行时连接
        String runtime3 = "HelloWorld";
        System.out.println("运行时连接相等: " + (runtime2 == runtime3)); // false
        
        // 5. final变量的特殊情况
        System.out.println("\n5. final变量的特殊情况:");
        final String finalStr = "Hello";
        String combined = finalStr + "World"; // 编译时可以确定
        String literal = "HelloWorld";
        System.out.println("final变量连接: " + (combined == literal)); // true
    }
    
    private static void demonstrateStringPoolMemory() {
        System.out.println("\n字符串池内存演示:");
        
        // 创建大量相同的字符串
        List<String> strings1 = new ArrayList<>();
        List<String> strings2 = new ArrayList<>();
        
        String commonString = "CommonString";
        
        // 使用字符串池
        for (int i = 0; i < 1000; i++) {
            strings1.add(commonString); // 所有引用指向同一个对象
        }
        
        // 不使用字符串池
        for (int i = 0; i < 1000; i++) {
            strings2.add(new String("CommonString")); // 每次创建新对象
        }
        
        System.out.println("使用字符串池的列表大小: " + strings1.size());
        System.out.println("不使用字符串池的列表大小: " + strings2.size());
        
        // 检查引用是否相同
        boolean sameReference1 = strings1.get(0) == strings1.get(999);
        boolean sameReference2 = strings2.get(0) == strings2.get(999);
        
        System.out.println("字符串池中引用相同: " + sameReference1); // true
        System.out.println("堆中引用相同: " + sameReference2); // false
        
        System.out.println("\n字符串池的优势:");
        System.out.println("- 内存节省:相同内容的字符串共享内存");
        System.out.println("- 比较效率:可以使用==进行快速比较");
        System.out.println("- 缓存效果:常用字符串保存在池中");
    }
}

10.1.2 String性能优化

import java.util.*;
import java.util.concurrent.*;
import java.util.stream.*;

/**
 * String性能优化演示
 */
public class StringPerformanceDemo {
    public static void main(String[] args) {
        System.out.println("=== String性能优化演示 ===");
        
        demonstrateConcatenationPerformance();
        demonstrateStringBuilderVsBuffer();
        demonstrateStringFormatPerformance();
        demonstrateStringComparisonPerformance();
        demonstrateBestPractices();
    }
    
    public static void demonstrateConcatenationPerformance() {
        System.out.println("\n--- 字符串拼接性能对比 ---");
        
        int iterations = 10000;
        String baseString = "Hello";
        
        // 1. 使用+操作符
        long startTime = System.nanoTime();
        String result1 = "";
        for (int i = 0; i < iterations; i++) {
            result1 += baseString;
        }
        long plusOperatorTime = System.nanoTime() - startTime;
        
        // 2. 使用StringBuilder
        startTime = System.nanoTime();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < iterations; i++) {
            sb.append(baseString);
        }
        String result2 = sb.toString();
        long stringBuilderTime = System.nanoTime() - startTime;
        
        // 3. 使用StringBuilder预分配容量
        startTime = System.nanoTime();
        StringBuilder sbWithCapacity = new StringBuilder(iterations * baseString.length());
        for (int i = 0; i < iterations; i++) {
            sbWithCapacity.append(baseString);
        }
        String result3 = sbWithCapacity.toString();
        long stringBuilderWithCapacityTime = System.nanoTime() - startTime;
        
        // 4. 使用StringJoiner
        startTime = System.nanoTime();
        StringJoiner joiner = new StringJoiner("");
        for (int i = 0; i < iterations; i++) {
            joiner.add(baseString);
        }
        String result4 = joiner.toString();
        long stringJoinerTime = System.nanoTime() - startTime;
        
        // 5. 使用Stream.collect
        startTime = System.nanoTime();
        String result5 = IntStream.range(0, iterations)
            .mapToObj(i -> baseString)
            .collect(Collectors.joining());
        long streamTime = System.nanoTime() - startTime;
        
        System.out.println("拼接" + iterations + "次字符串的性能对比:");
        System.out.println("+操作符: " + plusOperatorTime / 1_000_000 + "ms");
        System.out.println("StringBuilder: " + stringBuilderTime / 1_000_000 + "ms");
        System.out.println("StringBuilder(预分配): " + stringBuilderWithCapacityTime / 1_000_000 + "ms");
        System.out.println("StringJoiner: " + stringJoinerTime / 1_000_000 + "ms");
        System.out.println("Stream.collect: " + streamTime / 1_000_000 + "ms");
        
        System.out.println("\n性能提升倍数(相对于+操作符):");
        System.out.println("StringBuilder: " + (double) plusOperatorTime / stringBuilderTime + "倍");
        System.out.println("StringBuilder(预分配): " + (double) plusOperatorTime / stringBuilderWithCapacityTime + "倍");
        System.out.println("StringJoiner: " + (double) plusOperatorTime / stringJoinerTime + "倍");
        System.out.println("Stream.collect: " + (double) plusOperatorTime / streamTime + "倍");
        
        // 验证结果一致性
        System.out.println("\n结果一致性验证:");
        System.out.println("所有结果长度相等: " + 
            (result1.length() == result2.length() && 
             result2.length() == result3.length() && 
             result3.length() == result4.length() && 
             result4.length() == result5.length()));
    }
    
    public static void demonstrateStringBuilderVsBuffer() {
        System.out.println("\n--- StringBuilder vs StringBuffer ---");
        
        int iterations = 100000;
        String testString = "Test";
        
        // 1. StringBuilder(非线程安全)
        long startTime = System.nanoTime();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < iterations; i++) {
            sb.append(testString);
        }
        String result1 = sb.toString();
        long stringBuilderTime = System.nanoTime() - startTime;
        
        // 2. StringBuffer(线程安全)
        startTime = System.nanoTime();
        StringBuffer sbf = new StringBuffer();
        for (int i = 0; i < iterations; i++) {
            sbf.append(testString);
        }
        String result2 = sbf.toString();
        long stringBufferTime = System.nanoTime() - startTime;
        
        System.out.println("单线程性能对比:");
        System.out.println("StringBuilder: " + stringBuilderTime / 1_000_000 + "ms");
        System.out.println("StringBuffer: " + stringBufferTime / 1_000_000 + "ms");
        System.out.println("StringBuilder比StringBuffer快: " + 
            (double) stringBufferTime / stringBuilderTime + "倍");
        
        // 3. 多线程环境测试
        System.out.println("\n多线程环境测试:");
        demonstrateMultiThreadedStringBuilding();
    }
    
    private static void demonstrateMultiThreadedStringBuilding() {
        int threadCount = 10;
        int iterationsPerThread = 1000;
        
        // StringBuilder(非线程安全)
        StringBuilder unsafeSb = new StringBuilder();
        ExecutorService executor1 = Executors.newFixedThreadPool(threadCount);
        
        long startTime = System.nanoTime();
        for (int i = 0; i < threadCount; i++) {
            executor1.submit(() -> {
                for (int j = 0; j < iterationsPerThread; j++) {
                    unsafeSb.append("A");
                }
            });
        }
        
        executor1.shutdown();
        try {
            executor1.awaitTermination(5, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        long unsafeTime = System.nanoTime() - startTime;
        
        // StringBuffer(线程安全)
        StringBuffer safeSbf = new StringBuffer();
        ExecutorService executor2 = Executors.newFixedThreadPool(threadCount);
        
        startTime = System.nanoTime();
        for (int i = 0; i < threadCount; i++) {
            executor2.submit(() -> {
                for (int j = 0; j < iterationsPerThread; j++) {
                    safeSbf.append("A");
                }
            });
        }
        
        executor2.shutdown();
        try {
            executor2.awaitTermination(5, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        long safeTime = System.nanoTime() - startTime;
        
        System.out.println("多线程环境性能:");
        System.out.println("StringBuilder(非线程安全): " + unsafeTime / 1_000_000 + "ms");
        System.out.println("StringBuffer(线程安全): " + safeTime / 1_000_000 + "ms");
        
        int expectedLength = threadCount * iterationsPerThread;
        System.out.println("\n结果验证:");
        System.out.println("期望长度: " + expectedLength);
        System.out.println("StringBuilder实际长度: " + unsafeSb.length() + 
            (unsafeSb.length() == expectedLength ? " ✓" : " ✗ (数据竞争)"));
        System.out.println("StringBuffer实际长度: " + safeSbf.length() + 
            (safeSbf.length() == expectedLength ? " ✓" : " ✗"));
    }
    
    public static void demonstrateStringFormatPerformance() {
        System.out.println("\n--- 字符串格式化性能 ---");
        
        int iterations = 100000;
        String name = "张三";
        int age = 25;
        double score = 95.67;
        
        // 1. String.format()
        long startTime = System.nanoTime();
        for (int i = 0; i < iterations; i++) {
            String result = String.format("姓名: %s, 年龄: %d, 分数: %.2f", name, age, score);
        }
        long formatTime = System.nanoTime() - startTime;
        
        // 2. StringBuilder拼接
        startTime = System.nanoTime();
        for (int i = 0; i < iterations; i++) {
            StringBuilder sb = new StringBuilder();
            sb.append("姓名: ").append(name)
              .append(", 年龄: ").append(age)
              .append(", 分数: ").append(String.format("%.2f", score));
            String result = sb.toString();
        }
        long stringBuilderTime = System.nanoTime() - startTime;
        
        // 3. 简单字符串拼接
        startTime = System.nanoTime();
        for (int i = 0; i < iterations; i++) {
            String result = "姓名: " + name + ", 年龄: " + age + ", 分数: " + 
                String.format("%.2f", score);
        }
        long concatenationTime = System.nanoTime() - startTime;
        
        // 4. MessageFormat
        MessageFormat messageFormat = new MessageFormat("姓名: {0}, 年龄: {1}, 分数: {2,number,#.##}");
        startTime = System.nanoTime();
        for (int i = 0; i < iterations; i++) {
            String result = messageFormat.format(new Object[]{name, age, score});
        }
        long messageFormatTime = System.nanoTime() - startTime;
        
        System.out.println("格式化" + iterations + "次字符串的性能对比:");
        System.out.println("String.format(): " + formatTime / 1_000_000 + "ms");
        System.out.println("StringBuilder: " + stringBuilderTime / 1_000_000 + "ms");
        System.out.println("字符串拼接: " + concatenationTime / 1_000_000 + "ms");
        System.out.println("MessageFormat: " + messageFormatTime / 1_000_000 + "ms");
        
        System.out.println("\n性能排序(从快到慢):");
        Map<String, Long> results = new HashMap<>();
        results.put("StringBuilder", stringBuilderTime);
        results.put("字符串拼接", concatenationTime);
        results.put("String.format()", formatTime);
        results.put("MessageFormat", messageFormatTime);
        
        results.entrySet().stream()
            .sorted(Map.Entry.comparingByValue())
            .forEach(entry -> System.out.println(entry.getKey() + ": " + 
                entry.getValue() / 1_000_000 + "ms"));
    }
    
    public static void demonstrateStringComparisonPerformance() {
        System.out.println("\n--- 字符串比较性能 ---");
        
        int iterations = 1000000;
        String str1 = "Hello, World!";
        String str2 = "Hello, World!";
        String str3 = new String("Hello, World!");
        String str4 = "HELLO, WORLD!";
        
        // 1. == 比较
        long startTime = System.nanoTime();
        for (int i = 0; i < iterations; i++) {
            boolean result = str1 == str2;
        }
        long referenceComparisonTime = System.nanoTime() - startTime;
        
        // 2. equals() 比较
        startTime = System.nanoTime();
        for (int i = 0; i < iterations; i++) {
            boolean result = str1.equals(str3);
        }
        long equalsTime = System.nanoTime() - startTime;
        
        // 3. equalsIgnoreCase() 比较
        startTime = System.nanoTime();
        for (int i = 0; i < iterations; i++) {
            boolean result = str1.equalsIgnoreCase(str4);
        }
        long equalsIgnoreCaseTime = System.nanoTime() - startTime;
        
        // 4. compareTo() 比较
        startTime = System.nanoTime();
        for (int i = 0; i < iterations; i++) {
            int result = str1.compareTo(str3);
        }
        long compareToTime = System.nanoTime() - startTime;
        
        System.out.println("比较" + iterations + "次字符串的性能对比:");
        System.out.println("== 引用比较: " + referenceComparisonTime / 1_000_000 + "ms");
        System.out.println("equals() 内容比较: " + equalsTime / 1_000_000 + "ms");
        System.out.println("equalsIgnoreCase(): " + equalsIgnoreCaseTime / 1_000_000 + "ms");
        System.out.println("compareTo(): " + compareToTime / 1_000_000 + "ms");
        
        System.out.println("\n性能提升倍数(相对于equals):");
        System.out.println("== 比equals快: " + (double) equalsTime / referenceComparisonTime + "倍");
        System.out.println("equals比equalsIgnoreCase快: " + 
            (double) equalsIgnoreCaseTime / equalsTime + "倍");
        System.out.println("equals比compareTo快: " + (double) compareToTime / equalsTime + "倍");
    }
    
    public static void demonstrateBestPractices() {
        System.out.println("\n--- String性能最佳实践 ---");
        
        System.out.println("\n1. 字符串拼接最佳实践:");
        System.out.println("✓ 少量拼接:使用+操作符");
        System.out.println("✓ 循环拼接:使用StringBuilder");
        System.out.println("✓ 大量拼接:预分配StringBuilder容量");
        System.out.println("✓ 多线程拼接:使用StringBuffer或ThreadLocal<StringBuilder>");
        
        System.out.println("\n2. 字符串比较最佳实践:");
        System.out.println("✓ 引用比较:使用==(仅限字符串池中的字符串)");
        System.out.println("✓ 内容比较:使用equals()");
        System.out.println("✓ 忽略大小写:使用equalsIgnoreCase()");
        System.out.println("✓ 避免NullPointerException:使用Objects.equals()或常量.equals(变量)");
        
        System.out.println("\n3. 字符串创建最佳实践:");
        System.out.println("✓ 优先使用字面量:利用字符串池");
        System.out.println("✓ 避免不必要的new String()");
        System.out.println("✓ 使用intern()谨慎:只对重复使用的字符串");
        
        System.out.println("\n4. 内存优化最佳实践:");
        System.out.println("✓ 及时释放大字符串的引用");
        System.out.println("✓ 使用substring()时注意内存泄漏(Java 7之前)");
        System.out.println("✓ 考虑使用char[]代替String处理敏感数据");
        
        System.out.println("\n5. 格式化最佳实践:");
        System.out.println("✓ 简单格式化:使用StringBuilder");
        System.out.println("✓ 复杂格式化:使用String.format()");
        System.out.println("✓ 重复格式化:缓存MessageFormat实例");
        System.out.println("✓ 国际化:使用MessageFormat");
        
        // 演示最佳实践示例
        demonstrateBestPracticeExamples();
    }
    
    private static void demonstrateBestPracticeExamples() {
        System.out.println("\n--- 最佳实践示例 ---");
        
        // 1. 正确的字符串拼接
        System.out.println("\n1. 正确的字符串拼接:");
        
        // 少量拼接
        String simple = "Hello" + ", " + "World!";
        System.out.println("简单拼接: " + simple);
        
        // 循环拼接
        StringBuilder sb = new StringBuilder();
        for (int i = 1; i <= 5; i++) {
            sb.append("Item ").append(i).append("; ");
        }
        System.out.println("循环拼接: " + sb.toString());
        
        // 预分配容量
        List<String> items = Arrays.asList("Apple", "Banana", "Orange", "Grape");
        StringBuilder sbWithCapacity = new StringBuilder(items.size() * 10); // 估算容量
        for (String item : items) {
            sbWithCapacity.append(item).append(", ");
        }
        System.out.println("预分配容量: " + sbWithCapacity.toString());
        
        // 2. 安全的字符串比较
        System.out.println("\n2. 安全的字符串比较:");
        String nullableString = null;
        String constantString = "Hello";
        
        // 安全的比较方式
        System.out.println("安全比较1: " + Objects.equals(nullableString, constantString));
        System.out.println("安全比较2: " + constantString.equals(nullableString));
        
        // 3. 高效的字符串处理
        System.out.println("\n3. 高效的字符串处理:");
        String text = "  Hello, World!  ";
        
        // 链式调用
        String processed = text.trim().toLowerCase().replace("world", "java");
        System.out.println("链式处理: " + processed);
        
        // 使用Stream处理字符串集合
        List<String> words = Arrays.asList("apple", "banana", "ORANGE", "grape");
        String result = words.stream()
            .map(String::toLowerCase)
            .filter(word -> word.length() > 4)
            .collect(Collectors.joining(", "));
        System.out.println("Stream处理: " + result);
    }
}

10.2 StringBuilder和StringBuffer

10.2.1 StringBuilder详解

import java.util.*;
import java.util.stream.*;

/**
 * StringBuilder详细演示
 */
public class StringBuilderDemo {
    public static void main(String[] args) {
        System.out.println("=== StringBuilder详细演示 ===");
        
        demonstrateStringBuilderBasics();
        demonstrateStringBuilderMethods();
        demonstrateStringBuilderCapacity();
        demonstrateStringBuilderPerformance();
        demonstrateStringBuilderUseCases();
    }
    
    public static void demonstrateStringBuilderBasics() {
        System.out.println("\n--- StringBuilder基础 ---");
        
        // 1. 创建StringBuilder的不同方式
        System.out.println("\n1. 创建StringBuilder:");
        
        // 默认构造器(初始容量16)
        StringBuilder sb1 = new StringBuilder();
        System.out.println("默认构造器容量: " + sb1.capacity());
        
        // 指定初始容量
        StringBuilder sb2 = new StringBuilder(50);
        System.out.println("指定容量构造器: " + sb2.capacity());
        
        // 从字符串创建
        StringBuilder sb3 = new StringBuilder("Hello");
        System.out.println("从字符串创建: '" + sb3.toString() + "', 容量: " + sb3.capacity());
        
        // 从CharSequence创建
        StringBuilder sb4 = new StringBuilder(sb3);
        System.out.println("从CharSequence创建: '" + sb4.toString() + "'");
        
        // 2. StringBuilder的可变性
        System.out.println("\n2. StringBuilder的可变性:");
        StringBuilder mutableSb = new StringBuilder("Original");
        System.out.println("原始内容: " + mutableSb.toString());
        System.out.println("原始hashCode: " + mutableSb.hashCode());
        
        mutableSb.append(" Modified");
        System.out.println("修改后内容: " + mutableSb.toString());
        System.out.println("修改后hashCode: " + mutableSb.hashCode()); // 注意:可能相同或不同
        
        // 3. StringBuilder vs String
        System.out.println("\n3. StringBuilder vs String:");
        demonstrateStringBuilderVsString();
    }
    
    private static void demonstrateStringBuilderVsString() {
        System.out.println("\nStringBuilder vs String 对比:");
        
        int iterations = 1000;
        
        // String拼接
        long startTime = System.nanoTime();
        String str = "";
        for (int i = 0; i < iterations; i++) {
            str += "a";
        }
        long stringTime = System.nanoTime() - startTime;
        
        // StringBuilder拼接
        startTime = System.nanoTime();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < iterations; i++) {
            sb.append("a");
        }
        String sbResult = sb.toString();
        long sbTime = System.nanoTime() - startTime;
        
        System.out.println("String拼接时间: " + stringTime / 1_000_000 + "ms");
        System.out.println("StringBuilder拼接时间: " + sbTime / 1_000_000 + "ms");
        System.out.println("StringBuilder比String快: " + (double) stringTime / sbTime + "倍");
        System.out.println("结果长度相等: " + (str.length() == sbResult.length()));
    }
    
    public static void demonstrateStringBuilderMethods() {
        System.out.println("\n--- StringBuilder方法详解 ---");
        
        StringBuilder sb = new StringBuilder("Hello");
        
        // 1. 追加方法
        System.out.println("\n1. 追加方法:");
        System.out.println("初始内容: '" + sb.toString() + "'");
        
        sb.append(", World!");
        System.out.println("append(String): '" + sb.toString() + "'");
        
        sb.append(' ').append(123).append(' ').append(45.67);
        System.out.println("链式append: '" + sb.toString() + "'");
        
        sb.append(true).append(' ').append('X');
        System.out.println("append多种类型: '" + sb.toString() + "'");
        
        // append数组
        char[] chars = {'A', 'B', 'C'};
        sb.append(' ').append(chars);
        System.out.println("append字符数组: '" + sb.toString() + "'");
        
        sb.append(' ').append(chars, 1, 2); // 从索引1开始,长度为2
        System.out.println("append部分字符数组: '" + sb.toString() + "'");
        
        // 2. 插入方法
        System.out.println("\n2. 插入方法:");
        sb = new StringBuilder("Hello World");
        System.out.println("原始: '" + sb.toString() + "'");
        
        sb.insert(5, ", Beautiful");
        System.out.println("insert(5, String): '" + sb.toString() + "'");
        
        sb.insert(0, "Say: ");
        System.out.println("insert(0, String): '" + sb.toString() + "'");
        
        sb.insert(sb.length(), "!");
        System.out.println("insert(end, String): '" + sb.toString() + "'");
        
        // 3. 删除方法
        System.out.println("\n3. 删除方法:");
        sb = new StringBuilder("Hello, Beautiful World!");
        System.out.println("原始: '" + sb.toString() + "'");
        
        sb.delete(5, 17); // 删除", Beautiful"
        System.out.println("delete(5, 17): '" + sb.toString() + "'");
        
        sb.deleteCharAt(5); // 删除逗号
        System.out.println("deleteCharAt(5): '" + sb.toString() + "'");
        
        // 4. 替换方法
        System.out.println("\n4. 替换方法:");
        sb = new StringBuilder("Hello World");
        System.out.println("原始: '" + sb.toString() + "'");
        
        sb.replace(6, 11, "Java");
        System.out.println("replace(6, 11, 'Java'): '" + sb.toString() + "'");
        
        // 5. 反转方法
        System.out.println("\n5. 反转方法:");
        sb = new StringBuilder("Hello");
        System.out.println("原始: '" + sb.toString() + "'");
        
        sb.reverse();
        System.out.println("reverse(): '" + sb.toString() + "'");
        
        // 6. 查找方法
        System.out.println("\n6. 查找方法:");
        sb = new StringBuilder("Hello World Hello");
        System.out.println("内容: '" + sb.toString() + "'");
        
        System.out.println("indexOf('o'): " + sb.indexOf("o"));
        System.out.println("lastIndexOf('o'): " + sb.lastIndexOf("o"));
        System.out.println("indexOf('Hello', 1): " + sb.indexOf("Hello", 1));
        
        // 7. 字符访问和修改
        System.out.println("\n7. 字符访问和修改:");
        sb = new StringBuilder("Hello");
        System.out.println("原始: '" + sb.toString() + "'");
        
        System.out.println("charAt(1): " + sb.charAt(1));
        
        sb.setCharAt(1, 'a');
        System.out.println("setCharAt(1, 'a'): '" + sb.toString() + "'");
        
        // 8. 子序列方法
        System.out.println("\n8. 子序列方法:");
        sb = new StringBuilder("Hello World");
        System.out.println("原始: '" + sb.toString() + "'");
        
        CharSequence subSeq = sb.subSequence(6, 11);
        System.out.println("subSequence(6, 11): '" + subSeq.toString() + "'");
        
        String substring = sb.substring(6);
        System.out.println("substring(6): '" + substring + "'");
        
        String substring2 = sb.substring(0, 5);
        System.out.println("substring(0, 5): '" + substring2 + "'");
    }
    
    public static void demonstrateStringBuilderCapacity() {
        System.out.println("\n--- StringBuilder容量管理 ---");
        
        // 1. 容量的基本概念
        System.out.println("\n1. 容量基本概念:");
        StringBuilder sb = new StringBuilder();
        System.out.println("初始容量: " + sb.capacity());
        System.out.println("初始长度: " + sb.length());
        
        sb.append("Hello");
        System.out.println("添加'Hello'后容量: " + sb.capacity());
        System.out.println("添加'Hello'后长度: " + sb.length());
        
        // 2. 容量扩展机制
        System.out.println("\n2. 容量扩展机制:");
        sb = new StringBuilder(10);
        System.out.println("初始容量: " + sb.capacity());
        
        // 添加字符直到超过容量
        for (int i = 0; i < 15; i++) {
            sb.append('a');
            if (i == 9 || i == 14) {
                System.out.println("长度" + sb.length() + "时容量: " + sb.capacity());
            }
        }
        
        // 3. 手动容量管理
        System.out.println("\n3. 手动容量管理:");
        sb = new StringBuilder("Hello");
        System.out.println("原始容量: " + sb.capacity());
        
        sb.ensureCapacity(50);
        System.out.println("ensureCapacity(50)后: " + sb.capacity());
        
        sb.trimToSize();
        System.out.println("trimToSize()后: " + sb.capacity());
        System.out.println("当前长度: " + sb.length());
        
        // 4. 容量对性能的影响
        System.out.println("\n4. 容量对性能的影响:");
        demonstrateCapacityPerformance();
        
        // 5. 设置长度
        System.out.println("\n5. 设置长度:");
        sb = new StringBuilder("Hello World");
        System.out.println("原始: '" + sb.toString() + "', 长度: " + sb.length());
        
        sb.setLength(5);
        System.out.println("setLength(5): '" + sb.toString() + "', 长度: " + sb.length());
        
        sb.setLength(10);
        System.out.println("setLength(10): '" + sb.toString() + "', 长度: " + sb.length());
        System.out.println("注意:扩展部分用\\0填充");
    }
    
    private static void demonstrateCapacityPerformance() {
        int iterations = 10000;
        String testString = "Test";
        
        // 不预分配容量
        long startTime = System.nanoTime();
        StringBuilder sb1 = new StringBuilder();
        for (int i = 0; i < iterations; i++) {
            sb1.append(testString);
        }
        long noPreallocationTime = System.nanoTime() - startTime;
        
        // 预分配容量
        startTime = System.nanoTime();
        StringBuilder sb2 = new StringBuilder(iterations * testString.length());
        for (int i = 0; i < iterations; i++) {
            sb2.append(testString);
        }
        long preallocationTime = System.nanoTime() - startTime;
        
        System.out.println("不预分配容量: " + noPreallocationTime / 1_000_000 + "ms");
        System.out.println("预分配容量: " + preallocationTime / 1_000_000 + "ms");
        System.out.println("预分配比不预分配快: " + 
            (double) noPreallocationTime / preallocationTime + "倍");
    }
    
    public static void demonstrateStringBuilderPerformance() {
        System.out.println("\n--- StringBuilder性能特性 ---");
        
        // 1. 不同操作的性能
        System.out.println("\n1. 不同操作的性能对比:");
        int iterations = 100000;
        
        // append性能
        StringBuilder sb = new StringBuilder(iterations * 5);
        long startTime = System.nanoTime();
        for (int i = 0; i < iterations; i++) {
            sb.append("test");
        }
        long appendTime = System.nanoTime() - startTime;
        
        // insert性能(在开头插入)
        sb = new StringBuilder(iterations * 5);
        startTime = System.nanoTime();
        for (int i = 0; i < 1000; i++) { // 减少迭代次数,因为insert较慢
            sb.insert(0, "test");
        }
        long insertTime = System.nanoTime() - startTime;
        
        // delete性能
        sb = new StringBuilder();
        for (int i = 0; i < 1000; i++) {
            sb.append("test");
        }
        startTime = System.nanoTime();
        for (int i = 0; i < 500; i++) {
            if (sb.length() >= 4) {
                sb.delete(0, 4);
            }
        }
        long deleteTime = System.nanoTime() - startTime;
        
        System.out.println("append " + iterations + "次: " + appendTime / 1_000_000 + "ms");
        System.out.println("insert 1000次: " + insertTime / 1_000_000 + "ms");
        System.out.println("delete 500次: " + deleteTime / 1_000_000 + "ms");
        
        // 2. 内存使用分析
        System.out.println("\n2. 内存使用分析:");
        demonstrateMemoryUsage();
    }
    
    private static void demonstrateMemoryUsage() {
        System.out.println("\nStringBuilder内存使用分析:");
        
        // 创建不同大小的StringBuilder
        StringBuilder small = new StringBuilder("Hello");
        StringBuilder medium = new StringBuilder(1000);
        StringBuilder large = new StringBuilder(10000);
        
        System.out.println("小StringBuilder - 长度: " + small.length() + ", 容量: " + small.capacity());
        System.out.println("中StringBuilder - 长度: " + medium.length() + ", 容量: " + medium.capacity());
        System.out.println("大StringBuilder - 长度: " + large.length() + ", 容量: " + large.capacity());
        
        // 演示容量浪费
        StringBuilder wasteful = new StringBuilder(1000);
        wasteful.append("Small content");
        System.out.println("\n容量浪费示例:");
        System.out.println("分配容量: " + wasteful.capacity());
        System.out.println("实际使用: " + wasteful.length());
        System.out.println("浪费比例: " + (1.0 - (double)wasteful.length() / wasteful.capacity()) * 100 + "%");
        
        wasteful.trimToSize();
        System.out.println("trimToSize后容量: " + wasteful.capacity());
    }
    
    public static void demonstrateStringBuilderUseCases() {
        System.out.println("\n--- StringBuilder使用场景 ---");
        
        // 1. 动态SQL构建
        System.out.println("\n1. 动态SQL构建:");
        String sql = buildDynamicSQL("users", 
            Arrays.asList("name", "age", "email"), 
            Arrays.asList("age > 18", "status = 'active'"));
        System.out.println("动态SQL: " + sql);
        
        // 2. CSV数据生成
        System.out.println("\n2. CSV数据生成:");
        List<String[]> data = Arrays.asList(
            new String[]{"张三", "25", "工程师"},
            new String[]{"李四", "30", "设计师"},
            new String[]{"王五", "28", "产品经理"}
        );
        String csv = generateCSV(Arrays.asList("姓名", "年龄", "职位"), data);
        System.out.println("CSV数据:\n" + csv);
        
        // 3. HTML生成
        System.out.println("\n3. HTML生成:");
        String html = generateHTMLTable(Arrays.asList("姓名", "年龄", "职位"), data);
        System.out.println("HTML表格:\n" + html);
        
        // 4. 日志格式化
        System.out.println("\n4. 日志格式化:");
        String log = formatLogMessage("INFO", "UserService", "用户登录成功", 
            Map.of("userId", "12345", "ip", "192.168.1.1"));
        System.out.println("格式化日志: " + log);
        
        // 5. JSON构建(简单版)
        System.out.println("\n5. 简单JSON构建:");
        String json = buildSimpleJSON(Map.of(
            "name", "张三",
            "age", "25",
            "active", "true"
        ));
        System.out.println("JSON: " + json);
        
        // 6. 字符串模板
        System.out.println("\n6. 字符串模板:");
        String template = "Hello, {name}! You have {count} new messages.";
        String result = processTemplate(template, Map.of("name", "张三", "count", "5"));
        System.out.println("模板结果: " + result);
    }
    
    private static String buildDynamicSQL(String table, List<String> columns, List<String> conditions) {
        StringBuilder sql = new StringBuilder();
        
        // SELECT子句
        sql.append("SELECT ");
        sql.append(String.join(", ", columns));
        
        // FROM子句
        sql.append(" FROM ").append(table);
        
        // WHERE子句
        if (!conditions.isEmpty()) {
            sql.append(" WHERE ");
            sql.append(String.join(" AND ", conditions));
        }
        
        return sql.toString();
    }
    
    private static String generateCSV(List<String> headers, List<String[]> data) {
        StringBuilder csv = new StringBuilder();
        
        // 添加标题行
        csv.append(String.join(",", headers)).append("\n");
        
        // 添加数据行
        for (String[] row : data) {
            csv.append(String.join(",", row)).append("\n");
        }
        
        return csv.toString();
    }
    
    private static String generateHTMLTable(List<String> headers, List<String[]> data) {
        StringBuilder html = new StringBuilder();
        
        html.append("<table border='1'>\n");
        
        // 标题行
        html.append("  <thead>\n    <tr>\n");
        for (String header : headers) {
            html.append("      <th>").append(header).append("</th>\n");
        }
        html.append("    </tr>\n  </thead>\n");
        
        // 数据行
        html.append("  <tbody>\n");
        for (String[] row : data) {
            html.append("    <tr>\n");
            for (String cell : row) {
                html.append("      <td>").append(cell).append("</td>\n");
            }
            html.append("    </tr>\n");
        }
        html.append("  </tbody>\n");
        
        html.append("</table>");
        
        return html.toString();
    }
    
    private static String formatLogMessage(String level, String component, String message, Map<String, String> context) {
        StringBuilder log = new StringBuilder();
        
        log.append("[").append(new Date()).append("] ");
        log.append("[").append(level).append("] ");
        log.append("[").append(component).append("] ");
        log.append(message);
        
        if (!context.isEmpty()) {
            log.append(" - ");
            context.forEach((key, value) -> 
                log.append(key).append("=").append(value).append(", "));
            // 移除最后的逗号和空格
            log.setLength(log.length() - 2);
        }
        
        return log.toString();
    }
    
    private static String buildSimpleJSON(Map<String, String> data) {
        StringBuilder json = new StringBuilder();
        
        json.append("{");
        
        boolean first = true;
        for (Map.Entry<String, String> entry : data.entrySet()) {
            if (!first) {
                json.append(", ");
            }
            json.append('"').append(entry.getKey()).append('"');
            json.append(": ");
            
            // 简单的值处理(实际应用中需要更复杂的转义)
            String value = entry.getValue();
            if ("true".equals(value) || "false".equals(value) || value.matches("\\d+")) {
                json.append(value);
            } else {
                json.append('"').append(value).append('"');
            }
            
            first = false;
        }
        
        json.append("}");
        
        return json.toString();
    }
    
    private static String processTemplate(String template, Map<String, String> variables) {
        StringBuilder result = new StringBuilder(template);
        
        for (Map.Entry<String, String> entry : variables.entrySet()) {
            String placeholder = "{" + entry.getKey() + "}";
            int index = result.indexOf(placeholder);
            
            while (index != -1) {
                result.replace(index, index + placeholder.length(), entry.getValue());
                index = result.indexOf(placeholder, index + entry.getValue().length());
            }
        }
        
        return result.toString();
    }
}

10.2.2 StringBuffer详解

import java.util.concurrent.*;
import java.util.*;

/**
 * StringBuffer详细演示
 */
public class StringBufferDemo {
    public static void main(String[] args) {
        System.out.println("=== StringBuffer详细演示 ===");
        
        demonstrateStringBufferBasics();
        demonstrateThreadSafety();
        demonstrateStringBufferVsStringBuilder();
        demonstrateStringBufferUseCases();
    }
    
    public static void demonstrateStringBufferBasics() {
        System.out.println("\n--- StringBuffer基础 ---");
        
        // 1. StringBuffer的创建
        System.out.println("\n1. StringBuffer创建:");
        
        StringBuffer sb1 = new StringBuffer();
        System.out.println("默认构造器容量: " + sb1.capacity());
        
        StringBuffer sb2 = new StringBuffer(50);
        System.out.println("指定容量构造器: " + sb2.capacity());
        
        StringBuffer sb3 = new StringBuffer("Hello");
        System.out.println("从字符串创建: '" + sb3.toString() + "', 容量: " + sb3.capacity());
        
        // 2. 基本操作
        System.out.println("\n2. 基本操作:");
        StringBuffer sb = new StringBuffer("Hello");
        System.out.println("初始: '" + sb.toString() + "'");
        
        sb.append(", World!");
        System.out.println("append后: '" + sb.toString() + "'");
        
        sb.insert(5, " Beautiful");
        System.out.println("insert后: '" + sb.toString() + "'");
        
        sb.delete(5, 15);
        System.out.println("delete后: '" + sb.toString() + "'");
        
        sb.reverse();
        System.out.println("reverse后: '" + sb.toString() + "'");
        
        // 3. StringBuffer的同步特性
        System.out.println("\n3. StringBuffer的同步特性:");
        System.out.println("StringBuffer的所有方法都是synchronized的");
        System.out.println("这保证了线程安全,但也带来了性能开销");
        
        // 查看方法签名(通过反射)
        demonstrateStringBufferSynchronization();
    }
    
    private static void demonstrateStringBufferSynchronization() {
        System.out.println("\nStringBuffer方法同步验证:");
        
        try {
            Class<?> sbClass = StringBuffer.class;
            
            // 检查几个主要方法是否为synchronized
            String[] methodNames = {"append", "insert", "delete", "reverse", "toString"};
            
            for (String methodName : methodNames) {
                try {
                    var methods = sbClass.getDeclaredMethods();
                    boolean foundSynchronized = false;
                    
                    for (var method : methods) {
                        if (method.getName().equals(methodName)) {
                            int modifiers = method.getModifiers();
                            if (java.lang.reflect.Modifier.isSynchronized(modifiers)) {
                                foundSynchronized = true;
                                break;
                            }
                        }
                    }
                    
                    System.out.println(methodName + "方法是否synchronized: " + foundSynchronized);
                } catch (Exception e) {
                    System.out.println(methodName + "方法检查失败: " + e.getMessage());
                }
            }
        } catch (Exception e) {
            System.out.println("反射检查失败: " + e.getMessage());
        }
    }
    
    public static void demonstrateThreadSafety() {
        System.out.println("\n--- 线程安全演示 ---");
        
        int threadCount = 10;
        int operationsPerThread = 1000;
        
        // 1. StringBuffer线程安全测试
        System.out.println("\n1. StringBuffer线程安全测试:");
        StringBuffer safeBuffer = new StringBuffer();
        
        ExecutorService executor1 = Executors.newFixedThreadPool(threadCount);
        CountDownLatch latch1 = new CountDownLatch(threadCount);
        
        long startTime = System.nanoTime();
        
        for (int i = 0; i < threadCount; i++) {
            final int threadId = i;
            executor1.submit(() -> {
                try {
                    for (int j = 0; j < operationsPerThread; j++) {
                        safeBuffer.append("T" + threadId + "_" + j + ";");
                    }
                } finally {
                    latch1.countDown();
                }
            });
        }
        
        try {
            latch1.await();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        
        long safeTime = System.nanoTime() - startTime;
        executor1.shutdown();
        
        // 2. StringBuilder非线程安全对比
        System.out.println("\n2. StringBuilder非线程安全对比:");
        StringBuilder unsafeBuilder = new StringBuilder();
        
        ExecutorService executor2 = Executors.newFixedThreadPool(threadCount);
        CountDownLatch latch2 = new CountDownLatch(threadCount);
        
        startTime = System.nanoTime();
        
        for (int i = 0; i < threadCount; i++) {
            final int threadId = i;
            executor2.submit(() -> {
                try {
                    for (int j = 0; j < operationsPerThread; j++) {
                        unsafeBuilder.append("T" + threadId + "_" + j + ";");
                    }
                } finally {
                    latch2.countDown();
                }
            });
        }
        
        try {
            latch2.await();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        
        long unsafeTime = System.nanoTime() - startTime;
        executor2.shutdown();
        
        // 3. 结果分析
        System.out.println("\n3. 结果分析:");
        int expectedLength = threadCount * operationsPerThread;
        
        // 计算实际操作数(通过分号数量)
        int safeOperations = safeBuffer.toString().split(";").length - 1;
        int unsafeOperations = unsafeBuilder.toString().split(";").length - 1;
        
        System.out.println("期望操作数: " + expectedLength);
        System.out.println("StringBuffer实际操作数: " + safeOperations + 
            (safeOperations == expectedLength ? " ✓" : " ✗"));
        System.out.println("StringBuilder实际操作数: " + unsafeOperations + 
            (unsafeOperations == expectedLength ? " ✓" : " ✗ (数据竞争)"));
        
        System.out.println("\nStringBuffer执行时间: " + safeTime / 1_000_000 + "ms");
        System.out.println("StringBuilder执行时间: " + unsafeTime / 1_000_000 + "ms");
        
        if (unsafeTime > 0) {
            System.out.println("StringBuilder比StringBuffer快: " + 
                (double) safeTime / unsafeTime + "倍(但不安全)");
        }
    }
    
    public static void demonstrateStringBufferVsStringBuilder() {
        System.out.println("\n--- StringBuffer vs StringBuilder详细对比 ---");
        
        // 1. 功能对比
        System.out.println("\n1. 功能对比:");
        System.out.println("StringBuffer:");
        System.out.println("  - 线程安全(synchronized方法)");
        System.out.println("  - 性能较低(同步开销)");
        System.out.println("  - 适用于多线程环境");
        System.out.println("  - JDK 1.0引入");
        
        System.out.println("\nStringBuilder:");
        System.out.println("  - 非线程安全");
        System.out.println("  - 性能较高(无同步开销)");
        System.out.println("  - 适用于单线程环境");
        System.out.println("  - JDK 1.5引入");
        
        // 2. 性能对比
        System.out.println("\n2. 单线程性能对比:");
        performSingleThreadComparison();
        
        // 3. API兼容性
        System.out.println("\n3. API兼容性:");
        demonstrateAPICompatibility();
        
        // 4. 使用建议
        System.out.println("\n4. 使用建议:");
        System.out.println("✓ 单线程环境:优先使用StringBuilder");
        System.out.println("✓ 多线程环境:使用StringBuffer或ThreadLocal<StringBuilder>");
        System.out.println("✓ 性能敏感场景:考虑使用StringBuilder + 外部同步");
        System.out.println("✓ 遗留代码:StringBuffer可以直接替换为StringBuilder(注意线程安全)");
    }
    
    private static void performSingleThreadComparison() {
        int iterations = 100000;
        String testString = "Test";
        
        // StringBuffer测试
        long startTime = System.nanoTime();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < iterations; i++) {
            sb.append(testString);
        }
        String result1 = sb.toString();
        long stringBufferTime = System.nanoTime() - startTime;
        
        // StringBuilder测试
        startTime = System.nanoTime();
        StringBuilder sbd = new StringBuilder();
        for (int i = 0; i < iterations; i++) {
            sbd.append(testString);
        }
        String result2 = sbd.toString();
        long stringBuilderTime = System.nanoTime() - startTime;
        
        System.out.println("StringBuffer时间: " + stringBufferTime / 1_000_000 + "ms");
        System.out.println("StringBuilder时间: " + stringBuilderTime / 1_000_000 + "ms");
        System.out.println("StringBuilder比StringBuffer快: " + 
            (double) stringBufferTime / stringBuilderTime + "倍");
        System.out.println("结果一致: " + result1.equals(result2));
    }
    
    private static void demonstrateAPICompatibility() {
        System.out.println("\nAPI兼容性演示:");
        
        // 两者具有相同的API
        StringBuffer sb = new StringBuffer("Hello");
        StringBuilder sbd = new StringBuilder("Hello");
        
        // 相同的方法调用
        sb.append(", World!").insert(5, " Beautiful").reverse();
        sbd.append(", World!").insert(5, " Beautiful").reverse();
        
        System.out.println("StringBuffer结果: " + sb.toString());
        System.out.println("StringBuilder结果: " + sbd.toString());
        System.out.println("结果相同: " + sb.toString().equals(sbd.toString()));
        
        // 都实现了相同的接口
        System.out.println("\n接口实现:");
        System.out.println("StringBuffer实现Appendable: " + (sb instanceof Appendable));
        System.out.println("StringBuilder实现Appendable: " + (sbd instanceof Appendable));
        System.out.println("StringBuffer实现CharSequence: " + (sb instanceof CharSequence));
        System.out.println("StringBuilder实现CharSequence: " + (sbd instanceof CharSequence));
    }
    
    public static void demonstrateStringBufferUseCases() {
        System.out.println("\n--- StringBuffer使用场景 ---");
        
        // 1. 多线程日志收集
        System.out.println("\n1. 多线程日志收集:");
        demonstrateMultiThreadedLogging();
        
        // 2. 线程安全的缓存构建
        System.out.println("\n2. 线程安全的缓存构建:");
        demonstrateThreadSafeCache();
        
        // 3. 替代方案:ThreadLocal<StringBuilder>
        System.out.println("\n3. 替代方案:ThreadLocal<StringBuilder>:");
        demonstrateThreadLocalAlternative();
    }
    
    private static void demonstrateMultiThreadedLogging() {
        StringBuffer logBuffer = new StringBuffer();
        int threadCount = 5;
        int logsPerThread = 3;
        
        ExecutorService executor = Executors.newFixedThreadPool(threadCount);
        CountDownLatch latch = new CountDownLatch(threadCount);
        
        for (int i = 0; i < threadCount; i++) {
            final int threadId = i;
            executor.submit(() -> {
                try {
                    for (int j = 0; j < logsPerThread; j++) {
                        String logEntry = String.format("[Thread-%d] Log entry %d at %s\n", 
                            threadId, j, new Date());
                        logBuffer.append(logEntry);
                        
                        // 模拟一些处理时间
                        try {
                            Thread.sleep(10);
                        } catch (InterruptedException e) {
                            Thread.currentThread().interrupt();
                        }
                    }
                } finally {
                    latch.countDown();
                }
            });
        }
        
        try {
            latch.await();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        
        executor.shutdown();
        
        System.out.println("多线程日志收集结果:");
        System.out.println(logBuffer.toString());
        
        // 验证日志完整性
        String[] lines = logBuffer.toString().split("\n");
        System.out.println("总日志条数: " + lines.length + 
            " (期望: " + (threadCount * logsPerThread) + ")");
    }
    
    private static void demonstrateThreadSafeCache() {
        // 简单的线程安全缓存实现
        class ThreadSafeStringCache {
            private final StringBuffer cache = new StringBuffer();
            private final Set<String> keys = ConcurrentHashMap.newKeySet();
            
            public void addEntry(String key, String value) {
                if (keys.add(key)) { // 避免重复
                    cache.append(key).append("=").append(value).append(";");
                }
            }
            
            public String getCache() {
                return cache.toString();
            }
            
            public int size() {
                return keys.size();
            }
        }
        
        ThreadSafeStringCache cache = new ThreadSafeStringCache();
        int threadCount = 3;
        
        ExecutorService executor = Executors.newFixedThreadPool(threadCount);
        CountDownLatch latch = new CountDownLatch(threadCount);
        
        for (int i = 0; i < threadCount; i++) {
            final int threadId = i;
            executor.submit(() -> {
                try {
                    for (int j = 0; j < 5; j++) {
                        cache.addEntry("key_" + threadId + "_" + j, "value_" + threadId + "_" + j);
                    }
                } finally {
                    latch.countDown();
                }
            });
        }
        
        try {
            latch.await();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        
        executor.shutdown();
        
        System.out.println("线程安全缓存结果:");
        System.out.println("缓存内容: " + cache.getCache());
        System.out.println("缓存条目数: " + cache.size());
    }
    
    private static void demonstrateThreadLocalAlternative() {
        // ThreadLocal<StringBuilder>作为StringBuffer的替代方案
        ThreadLocal<StringBuilder> threadLocalBuilder = ThreadLocal.withInitial(StringBuilder::new);
        
        class ThreadLocalStringProcessor {
            public String processInCurrentThread(String... inputs) {
                StringBuilder sb = threadLocalBuilder.get();
                sb.setLength(0); // 清空之前的内容
                
                for (String input : inputs) {
                    sb.append("[").append(Thread.currentThread().getName()).append("] ")
                      .append(input).append("\n");
                }
                
                return sb.toString();
            }
        }
        
        ThreadLocalStringProcessor processor = new ThreadLocalStringProcessor();
        
        // 在不同线程中使用
        ExecutorService executor = Executors.newFixedThreadPool(3);
        List<Future<String>> futures = new ArrayList<>();
        
        for (int i = 0; i < 3; i++) {
            final int threadId = i;
            Future<String> future = executor.submit(() -> 
                processor.processInCurrentThread("Message 1 from thread " + threadId, 
                                               "Message 2 from thread " + threadId));
            futures.add(future);
        }
        
        System.out.println("ThreadLocal<StringBuilder>结果:");
        for (int i = 0; i < futures.size(); i++) {
            try {
                System.out.println("Thread " + i + " result:\n" + futures.get(i).get());
            } catch (Exception e) {
                System.err.println("获取结果失败: " + e.getMessage());
            }
        }
        
        executor.shutdown();
        
        System.out.println("ThreadLocal优势:");
        System.out.println("- 每个线程有独立的StringBuilder实例");
        System.out.println("- 无需同步,性能更好");
        System.out.println("- 避免线程间的竞争");
        System.out.println("- 注意:需要及时清理避免内存泄漏");
    }
}

10.3 正则表达式

10.3.1 正则表达式基础

import java.util.regex.*;
import java.util.*;

/**
 * 正则表达式基础演示
 */
public class RegexBasicsDemo {
    public static void main(String[] args) {
        System.out.println("=== 正则表达式基础演示 ===");
        
        demonstrateRegexBasics();
        demonstratePatternAndMatcher();
        demonstrateCommonPatterns();
        demonstrateRegexFlags();
        demonstrateStringRegexMethods();
    }
    
    public static void demonstrateRegexBasics() {
        System.out.println("\n--- 正则表达式基础 ---");
        
        // 1. 基本概念
        System.out.println("\n1. 基本概念:");
        System.out.println("正则表达式(Regular Expression)是用于匹配字符串模式的强大工具");
        System.out.println("Java中主要通过Pattern和Matcher类来使用正则表达式");
        
        // 2. 基本字符匹配
        System.out.println("\n2. 基本字符匹配:");
        String text = "Hello World 123";
        
        System.out.println("文本: " + text);
        System.out.println("匹配'Hello': " + text.matches(".*Hello.*"));
        System.out.println("匹配'hello'(忽略大小写): " + 
            Pattern.compile(".*hello.*", Pattern.CASE_INSENSITIVE).matcher(text).matches());
        
        // 3. 元字符介绍
        System.out.println("\n3. 常用元字符:");
        System.out.println(". - 匹配任意单个字符(除换行符)");
        System.out.println("* - 匹配前面的字符0次或多次");
        System.out.println("+ - 匹配前面的字符1次或多次");
        System.out.println("? - 匹配前面的字符0次或1次");
        System.out.println("^ - 匹配字符串开始");
        System.out.println("$ - 匹配字符串结束");
        System.out.println("[] - 字符类,匹配括号内的任意字符");
        System.out.println("() - 分组");
        System.out.println("| - 或操作");
        System.out.println("\\ - 转义字符");
        
        // 4. 简单示例
        System.out.println("\n4. 简单示例:");
        demonstrateBasicExamples();
    }
    
    private static void demonstrateBasicExamples() {
        String[] texts = {"cat", "bat", "rat", "hat", "dog", "car"};
        String pattern = "[cbr]at"; // 匹配cat, bat, rat
        
        System.out.println("模式: " + pattern);
        System.out.println("测试文本: " + Arrays.toString(texts));
        
        Pattern p = Pattern.compile(pattern);
        for (String text : texts) {
            boolean matches = p.matcher(text).matches();
            System.out.println("'" + text + "' 匹配: " + matches);
        }
    }
    
    public static void demonstratePatternAndMatcher() {
        System.out.println("\n--- Pattern和Matcher类 ---");
        
        // 1. Pattern类
        System.out.println("\n1. Pattern类:");
        String regex = "\\d{3}-\\d{3}-\\d{4}"; // 电话号码格式
        Pattern pattern = Pattern.compile(regex);
        
        System.out.println("编译的正则表达式: " + pattern.pattern());
        System.out.println("标志位: " + pattern.flags());
        
        // 2. Matcher类
        System.out.println("\n2. Matcher类:");
        String text = "我的电话是123-456-7890,办公电话是987-654-3210";
        Matcher matcher = pattern.matcher(text);
        
        System.out.println("文本: " + text);
        System.out.println("查找所有匹配:");
        
        while (matcher.find()) {
            System.out.println("找到: " + matcher.group() + 
                " 位置: " + matcher.start() + "-" + matcher.end());
        }
        
        // 3. 重置Matcher
        System.out.println("\n3. 重置Matcher:");
        matcher.reset();
        System.out.println("重置后查找第一个匹配: " + matcher.find());
        if (matcher.find()) {
            System.out.println("第一个匹配: " + matcher.group());
        }
        
        // 4. 替换操作
        System.out.println("\n4. 替换操作:");
        matcher.reset();
        String replaced = matcher.replaceAll("XXX-XXX-XXXX");
        System.out.println("替换后: " + replaced);
        
        matcher.reset();
        String replacedFirst = matcher.replaceFirst("[隐藏]");
        System.out.println("只替换第一个: " + replacedFirst);
    }
    
    public static void demonstrateCommonPatterns() {
        System.out.println("\n--- 常用正则表达式模式 ---");
        
        // 定义常用模式
        Map<String, String> patterns = new LinkedHashMap<>();
        patterns.put("邮箱", "[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}");
        patterns.put("手机号", "1[3-9]\\d{9}");
        patterns.put("身份证", "\\d{17}[\\dXx]");
        patterns.put("IP地址", "((25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.){3}(25[0-5]|2[0-4]\\d|[01]?\\d\\d?)");
        patterns.put("URL", "https?://[\\w\\-]+(\\.[\\w\\-]+)+([\\w\\-\\.,@?^=%&:/~\\+#]*[\\w\\-\\@?^=%&/~\\+#])?");
        patterns.put("日期(yyyy-mm-dd)", "\\d{4}-\\d{2}-\\d{2}");
        patterns.put("时间(hh:mm:ss)", "([01]?\\d|2[0-3]):[0-5]\\d:[0-5]\\d");
        patterns.put("中文字符", "[\\u4e00-\\u9fa5]+");
        patterns.put("数字(整数)", "-?\\d+");
        patterns.put("数字(小数)", "-?\\d+(\\.\\d+)?");
        
        // 测试数据
        Map<String, String[]> testData = new HashMap<>();
        testData.put("邮箱", new String[]{"user@example.com", "test.email+tag@domain.co.uk", "invalid.email"});
        testData.put("手机号", new String[]{"13812345678", "15987654321", "12345678901"});
        testData.put("身份证", new String[]{"123456789012345678", "12345678901234567X", "1234567890"});
        testData.put("IP地址", new String[]{"192.168.1.1", "255.255.255.255", "256.1.1.1"});
        testData.put("URL", new String[]{"https://www.example.com", "http://test.com/path?param=value", "ftp://invalid"});
        testData.put("日期(yyyy-mm-dd)", new String[]{"2023-12-25", "2023-02-29", "23-12-25"});
        testData.put("时间(hh:mm:ss)", new String[]{"14:30:45", "23:59:59", "25:00:00"});
        testData.put("中文字符", new String[]{"你好世界", "Hello世界", "123"});
        testData.put("数字(整数)", new String[]{"123", "-456", "12.34"});
        testData.put("数字(小数)", new String[]{"123.45", "-67.89", "abc"});
        
        // 测试每个模式
        for (Map.Entry<String, String> entry : patterns.entrySet()) {
            String name = entry.getKey();
            String regex = entry.getValue();
            String[] tests = testData.get(name);
            
            System.out.println("\n" + name + " 模式: " + regex);
            
            if (tests != null) {
                Pattern pattern = Pattern.compile(regex);
                for (String test : tests) {
                    boolean matches = pattern.matcher(test).matches();
                    System.out.println("  '" + test + "' -> " + (matches ? "✓" : "✗"));
                }
            }
        }
    }
    
    public static void demonstrateRegexFlags() {
        System.out.println("\n--- 正则表达式标志位 ---");
        
        String text = "Hello\nWORLD\nJava";
        System.out.println("测试文本: " + text.replace("\n", "\\n"));
        
        // 1. CASE_INSENSITIVE - 忽略大小写
        System.out.println("\n1. CASE_INSENSITIVE - 忽略大小写:");
        Pattern pattern1 = Pattern.compile("hello", Pattern.CASE_INSENSITIVE);
        System.out.println("模式'hello'(忽略大小写)匹配: " + pattern1.matcher(text).find());
        
        Pattern pattern2 = Pattern.compile("hello");
        System.out.println("模式'hello'(区分大小写)匹配: " + pattern2.matcher(text).find());
        
        // 2. MULTILINE - 多行模式
        System.out.println("\n2. MULTILINE - 多行模式:");
        Pattern pattern3 = Pattern.compile("^WORLD$", Pattern.MULTILINE);
        System.out.println("多行模式下'^WORLD$'匹配: " + pattern3.matcher(text).find());
        
        Pattern pattern4 = Pattern.compile("^WORLD$");
        System.out.println("单行模式下'^WORLD$'匹配: " + pattern4.matcher(text).find());
        
        // 3. DOTALL - 点号匹配所有字符
        System.out.println("\n3. DOTALL - 点号匹配所有字符:");
        Pattern pattern5 = Pattern.compile("Hello.*Java", Pattern.DOTALL);
        System.out.println("DOTALL模式下'Hello.*Java'匹配: " + pattern5.matcher(text).find());
        
        Pattern pattern6 = Pattern.compile("Hello.*Java");
        System.out.println("普通模式下'Hello.*Java'匹配: " + pattern6.matcher(text).find());
        
        // 4. 组合标志位
        System.out.println("\n4. 组合标志位:");
        Pattern pattern7 = Pattern.compile("hello.*java", 
            Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
        System.out.println("组合标志位'hello.*java'匹配: " + pattern7.matcher(text).find());
        
        // 5. 在正则表达式中使用标志位
        System.out.println("\n5. 在正则表达式中使用标志位:");
        Pattern pattern8 = Pattern.compile("(?i)hello.*(?s)java"); // (?i)忽略大小写,(?s)点号匹配所有
        System.out.println("内联标志位'(?i)hello.*(?s)java'匹配: " + pattern8.matcher(text).find());
        
        // 6. 所有标志位说明
        System.out.println("\n6. 所有标志位说明:");
        System.out.println("CASE_INSENSITIVE (2): 忽略大小写");
        System.out.println("MULTILINE (8): ^和$匹配行的开始和结束");
        System.out.println("DOTALL (32): .匹配包括换行符在内的所有字符");
        System.out.println("UNICODE_CASE (64): 与CASE_INSENSITIVE一起使用,支持Unicode");
        System.out.println("CANON_EQ (128): 考虑Unicode规范等价");
        System.out.println("UNIX_LINES (1): 只有\\n被认为是行终止符");
        System.out.println("LITERAL (16): 将模式作为字面量处理");
        System.out.println("UNICODE_CHARACTER_CLASS (256): 启用Unicode字符类");
        System.out.println("COMMENTS (4): 允许在模式中使用空白和注释");
    }
    
    public static void demonstrateStringRegexMethods() {
        System.out.println("\n--- String类的正则表达式方法 ---");
        
        String text = "Java is great, Java is powerful, Java is everywhere!";
        System.out.println("原始文本: " + text);
        
        // 1. matches() - 完全匹配
        System.out.println("\n1. matches() - 完全匹配:");
        System.out.println("完全匹配'Java.*': " + text.matches("Java.*"));
        System.out.println("完全匹配'.*Java.*': " + text.matches(".*Java.*"));
        
        // 2. split() - 分割字符串
        System.out.println("\n2. split() - 分割字符串:");
        String[] parts1 = text.split(", ");
        System.out.println("按', '分割: " + Arrays.toString(parts1));
        
        String[] parts2 = text.split("\\s+"); // 按空白字符分割
        System.out.println("按空白字符分割: " + Arrays.toString(parts2));
        
        String[] parts3 = text.split("Java");
        System.out.println("按'Java'分割: " + Arrays.toString(parts3));
        
        // 限制分割数量
        String[] parts4 = text.split(", ", 2);
        System.out.println("限制分割为2部分: " + Arrays.toString(parts4));
        
        // 3. replaceAll() - 替换所有匹配
        System.out.println("\n3. replaceAll() - 替换所有匹配:");
        String replaced1 = text.replaceAll("Java", "Python");
        System.out.println("替换'Java'为'Python': " + replaced1);
        
        String replaced2 = text.replaceAll("\\bis\\b", "was"); // 单词边界
        System.out.println("替换单词'is'为'was': " + replaced2);
        
        // 4. replaceFirst() - 替换第一个匹配
        System.out.println("\n4. replaceFirst() - 替换第一个匹配:");
        String replaced3 = text.replaceFirst("Java", "Python");
        System.out.println("只替换第一个'Java': " + replaced3);
        
        // 5. 复杂的替换示例
        System.out.println("\n5. 复杂的替换示例:");
        String phoneText = "联系电话:123-456-7890 或 987-654-3210";
        System.out.println("原始: " + phoneText);
        
        // 使用分组进行替换
        String maskedPhone = phoneText.replaceAll("(\\d{3})-(\\d{3})-(\\d{4})", "$1-XXX-$3");
        System.out.println("掩码中间部分: " + maskedPhone);
        
        // 6. 实用示例
        System.out.println("\n6. 实用示例:");
        demonstrateStringRegexExamples();
    }
    
    private static void demonstrateStringRegexExamples() {
        // 清理HTML标签
        String html = "<p>这是一个<strong>重要</strong>的<em>消息</em>。</p>";
        String cleanText = html.replaceAll("<[^>]+>", "");
        System.out.println("清理HTML: " + html + " -> " + cleanText);
        
        // 提取数字
        String mixedText = "价格是$123.45,折扣10%,总计$111.11";
        String[] numbers = mixedText.split("[^\\d.]+");
        System.out.println("提取数字: " + mixedText);
        System.out.println("数字: " + Arrays.toString(Arrays.stream(numbers)
            .filter(s -> !s.isEmpty() && s.matches("\\d+(\\.\\d+)?"))
            .toArray()));
        
        // 验证邮箱格式
        String[] emails = {"user@example.com", "invalid.email", "test@domain.co.uk"};
        String emailPattern = "[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}";
        
        System.out.println("\n邮箱验证:");
        for (String email : emails) {
            boolean valid = email.matches(emailPattern);
            System.out.println(email + " -> " + (valid ? "有效" : "无效"));
        }
        
        // 格式化文本
        String messyText = "  hello    world   java   ";
        String formatted = messyText.trim().replaceAll("\\s+", " ");
        System.out.println("\n格式化文本: '" + messyText + "' -> '" + formatted + "'");
    }
}