ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Java String类详解:不可变性、核心方法与性能优化

Java String类详解:不可变性、核心方法与性能优化 1. Java String类基础解析String类是Java语言中最基础也最常用的类之一它代表不可变的字符序列。在Java中所有用双引号括起来的字符串如Hello World都是String类的实例。1.1 String类的不可变性String对象一旦创建其内容就不能被改变。这种设计带来了几个重要特性线程安全由于不可变String对象可以被多个线程安全共享缓存哈希值String类缓存了hashCode()的计算结果因为内容不变哈希值也不会变字符串池优化JVM可以使用字符串池来存储字符串字面量节省内存String s1 hello; String s2 s1.concat( world); // 创建新对象s1不变 System.out.println(s1); // 输出hello System.out.println(s2); // 输出hello world1.2 String的创建方式Java中创建String对象主要有两种方式字面量方式直接使用双引号创建String s1 hello;new关键字方式通过构造函数创建String s2 new String(hello);这两种方式在内存分配上有重要区别字面量方式会检查字符串池如果存在则直接引用否则创建新对象并放入池中new方式每次都会在堆中创建新对象不检查字符串池2. String类的核心方法详解2.1 字符串比较方法String类提供了多种比较方法各有不同的用途equals()比较字符串内容是否相同String s1 hello; String s2 HELLO; System.out.println(s1.equals(s2)); // falseequalsIgnoreCase()忽略大小写比较内容System.out.println(s1.equalsIgnoreCase(s2)); // truecompareTo()按字典顺序比较字符串System.out.println(apple.compareTo(banana)); // 负数运算符比较对象引用是否相同String s3 hello; String s4 hello; String s5 new String(hello); System.out.println(s3 s4); // true System.out.println(s3 s5); // false2.2 字符串查找方法String类提供了丰富的查找方法indexOf()查找字符或子串首次出现的位置String str Hello World; System.out.println(str.indexOf(o)); // 4 System.out.println(str.indexOf(World)); // 6lastIndexOf()查找字符或子串最后一次出现的位置System.out.println(str.lastIndexOf(o)); // 7contains()检查是否包含指定字符序列System.out.println(str.contains(llo)); // truestartsWith()/endsWith()检查字符串开头/结尾System.out.println(str.startsWith(Hello)); // true System.out.println(str.endsWith(ld)); // true2.3 字符串操作与转换substring()获取子字符串System.out.println(str.substring(6)); // World System.out.println(str.substring(0, 5)); // Helloconcat()连接字符串System.out.println(Hello.concat( World)); // Hello Worldreplace()替换字符或字符串System.out.println(hello.replace(l, L)); // heLLotoUpperCase()/toLowerCase()大小写转换System.out.println(str.toUpperCase()); // HELLO WORLDtrim()去除首尾空白字符System.out.println( hello .trim()); // hello3. String与正则表达式String类提供了强大的正则表达式支持3.1 matches()方法检查整个字符串是否匹配正则表达式String email testexample.com; System.out.println(email.matches(^[\\w-][\\w-]\\.[a-z]{2,3}$)); // true3.2 split()方法根据正则表达式分割字符串String data apple,orange,banana; String[] fruits data.split(,); for (String fruit : fruits) { System.out.println(fruit); }3.3 replaceAll()/replaceFirst()方法使用正则表达式替换String text foo123bar456baz; System.out.println(text.replaceAll(\\d, -)); // foo-bar-baz System.out.println(text.replaceFirst(\\d, -)); // foo-bar456baz4. String与字符编码4.1 编码转换String类提供了与字节数组相互转换的方法支持指定字符集String str 你好; byte[] utf8Bytes str.getBytes(StandardCharsets.UTF_8); String newStr new String(utf8Bytes, StandardCharsets.UTF_8);4.2 字符集注意事项默认使用平台字符集可能导致跨平台问题推荐明确指定字符集如UTF-8处理IO时字符集不一致会导致乱码5. String性能优化5.1 字符串拼接的优化使用StringBuilder进行多次拼接StringBuilder sb new StringBuilder(); for (int i 0; i 100; i) { sb.append(i).append(, ); } String result sb.toString();避免在循环中使用操作符拼接字符串// 低效做法 String s ; for (int i 0; i 100; i) { s i; // 每次循环创建新String对象 }5.2 字符串池的利用尽量使用字面量方式创建字符串使用intern()方法将字符串显式加入字符串池String s1 new String(hello).intern(); String s2 hello; System.out.println(s1 s2); // true6. 常见问题与解决方案6.1 字符串比较问题问题使用比较字符串内容String s1 hello; String s2 new String(hello); System.out.println(s1 s2); // false解决方案始终使用equals()方法比较内容6.2 字符串不可变导致的性能问题问题频繁修改字符串产生大量临时对象String s ; for (int i 0; i 10000; i) { s i; // 性能极差 }解决方案使用StringBuilder6.3 内存泄漏问题问题超大字符串的子字符串保持原字符串引用String huge ...非常长的字符串...; String small huge.substring(0, 10); // small仍引用huge的char[]解决方案(Java 7)使用new String(small)切断引用6.4 编码转换问题问题未指定字符集导致乱码byte[] bytes 你好.getBytes(); // 使用平台默认字符集 String s new String(bytes, ISO-8859-1); // 乱码解决方案始终明确指定字符集byte[] bytes 你好.getBytes(StandardCharsets.UTF_8); String s new String(bytes, StandardCharsets.UTF_8);7. Java 8及以后版本的String增强7.1 Java 8的StringJoiner简化字符串拼接StringJoiner sj new StringJoiner(, , [, ]); sj.add(apple).add(orange).add(banana); System.out.println(sj.toString()); // [apple, orange, banana]7.2 Java 11的String新方法isBlank()检查字符串是否为空或仅包含空白字符System.out.println( .isBlank()); // truelines()将字符串按行分割为流String text line1\nline2\nline3; text.lines().forEach(System.out::println);repeat()重复字符串System.out.println(abc.repeat(3)); // abcabcabcstrip()去除首尾空白字符比trim()更严格System.out.println( hello .strip()); // hello8. 实际应用案例8.1 字符串反转public static String reverse(String input) { return new StringBuilder(input).reverse().toString(); }8.2 检查回文字符串public static boolean isPalindrome(String str) { String clean str.replaceAll(\\s, ).toLowerCase(); return new StringBuilder(clean).reverse().toString().equals(clean); }8.3 统计字符出现次数public static int countChar(String str, char c) { return (int) str.chars().filter(ch - ch c).count(); }8.4 字符串格式化String formatted String.format(Name: %s, Age: %d, Salary: %.2f, John, 30, 5000.555); System.out.println(formatted); // Name: John, Age: 30, Salary: 5000.569. String与集合框架9.1 字符串排序ListString names Arrays.asList(John, Alice, Bob, Charlie); Collections.sort(names); // 自然顺序排序 names.sort(Comparator.comparingInt(String::length)); // 按长度排序9.2 字符串过滤ListString list Arrays.asList(apple, banana, cherry, date); ListString filtered list.stream() .filter(s - s.startsWith(a)) .collect(Collectors.toList());9.3 字符串分组ListString words Arrays.asList(apple, banana, apricot, berry); MapCharacter, ListString grouped words.stream() .collect(Collectors.groupingBy( s - s.charAt(0)));10. 高级话题String与JVM10.1 字符串池的实现JVM维护一个字符串常量池String Pool字面量字符串自动入池可以手动调用intern()方法入池Java 7将字符串池从永久代移到堆中10.2 字符串的内存占用每个String对象包含对象头12-16字节取决于JVMchar[]数组引用4-8字节哈希值缓存4字节char[]数组本身占用内存2字节 × 字符数 数组对象头10.3 字符串压缩Java 9引入了紧凑字符串Compact Strings对于仅含Latin-1字符的字符串使用byte[]而非char[]存储节省约50%内存完全透明无需修改代码11. 最佳实践总结优先使用字符串字面量而非new String()多字符串拼接使用StringBuilder比较字符串内容始终使用equals()而非明确指定字符集以避免编码问题利用Java新版本提供的字符串方法简化代码注意字符串操作在循环中的性能影响处理用户输入时总是进行空检查和trim()对于大量文本处理考虑使用更专业的类如StringBuffer(线程安全)或第三方库了解JVM字符串优化特性如Java 9的紧凑字符串在性能敏感场景考虑直接操作char[]或使用更高效的数据结构
返回列表