我們來系統地梳理一下 Java 中的字符串操作。Java 的字符串操作非常豐富,主要涉及到?String
、StringBuilder
?和?StringBuffer
?這三個核心類。
目錄
一、核心類簡介
二、String?類的常用操作
1. 創建字符串
2. 獲取基本信息
3. 比較字符串
4. 查找與判斷
5. 轉換與替換
6. 分割與連接
三、StringBuilder?/?StringBuffer?的常用操作
1. 創建對象
2. 修改字符串(核心功能)
四、性能對比:+?拼接 vs?StringBuilder
1.錯誤示例:使用?+?拼接
2.正確示例:使用?StringBuilder
一、核心類簡介
在開始具體操作前,先理解這三個類的區別至關重要:
import java.lang.StringBuilder;
類 | 特性 | 線程安全 | 性能 | 適用場景 |
---|---|---|---|---|
String | 不可變?(Immutable) | 是 | 較低(每次修改都創建新對象) | 字符串內容不需要改變的場景,如作為常量、Map 的鍵等。 |
StringBuilder | 可變?(Mutable) | 否 | 最高 | 單線程環境下,需要頻繁修改字符串內容(拼接、刪除、替換等)。 |
StringBuffer | 可變?(Mutable) | 是 | 較低(因為有同步開銷) | 多線程環境下,需要安全地修改字符串內容。 |
核心結論:
- 如果字符串內容不改變,用?
String
。 - 如果在單線程下需要頻繁修改字符串,用?
StringBuilder
。 - 如果在多線程下需要安全地修改字符串,用?
StringBuffer
。
二、String
?類的常用操作
String
?類提供了大量用于處理字符串的方法。
1. 創建字符串
// 1. 直接賦值 (推薦,JVM 會有字符串常量池優化)
String str1 = "Hello Java";// 2. 使用 new 關鍵字 (會創建新的對象,不推薦)
String str2 = new String("Hello Java");
2. 獲取基本信息
String str = "Hello World";
System.out.println(str.length()); // 獲取長度: 11
System.out.println(str.isEmpty()); // 判斷是否為空字符串: false
System.out.println(str.charAt(0)); // 獲取指定索引的字符: 'H'
System.out.println(str.indexOf('W')); // 查找字符 'W' 的索引: 6
System.out.println(str.indexOf("World")); // 查找子串 "World" 的索引: 6
System.out.println(str.lastIndexOf('o')); // 從后向前查找字符 'o' 的索引: 7
3. 比較字符串
String s1 = "hello";
String s2 = "world";
String s3 = "Hello";// 1. equals() : 比較內容是否相等 (區分大小寫)
System.out.println(s1.equals(s2)); // false// 2. equalsIgnoreCase() : 比較內容是否相等 (不區分大小寫)
System.out.println(s1.equalsIgnoreCase(s3)); // true// 3. compareTo() : 比較字典順序
// s1 < s2 返回負數, s1 == s2 返回 0, s1 > s2 返回正數
System.out.println(s1.compareTo(s2)); // -15 (h 的 ASCII 碼比 w 小)// 4. == : 比較的是兩個對象的內存地址 (是否是同一個對象)
String s4 = "hello";
String s5 = new String("hello");
System.out.println(s1 == s4); // true (字符串常量池,指向同一個對象)
System.out.println(s1 == s5); // false (new 創建了新對象,地址不同)
4. 查找與判斷
String str = "This is a test string.";System.out.println(str.contains("test")); // 判斷是否包含子串: true
System.out.println(str.startsWith("This")); // 判斷是否以指定前綴開頭: true
System.out.println(str.endsWith("ing.")); // 判斷是否以指定后綴結尾: true
System.out.println(str.substring(5)); // 從索引 5 開始截取到末尾: "is a test string."
System.out.println(str.substring(5, 7)); // 截取 [5, 7) 區間: "is"
5. 轉換與替換
String str = " Hello World ";// 1. trim() : 去除首尾空格
System.out.println(str.trim()); // "Hello World"// 2. toUpperCase() / toLowerCase() : 大小寫轉換
System.out.println(str.toUpperCase()); // " HELLO WORLD "
System.out.println(str.toLowerCase()); // " hello world "// 3. replace() : 替換字符或子串
// 注意:String 不可變,replace() 返回一個新字符串
String newStr = str.replace('l', 'p');
System.out.println(newStr); // " Heppo Worpd "
System.out.println(str.replace("World", "Java")); // " Hello Java "
6. 分割與連接
String str = "apple,banana,orange,grape";// 1. split() : 分割字符串,返回一個字符串數組
String[] fruits = str.split(",");
// fruits: ["apple", "banana", "orange", "grape"]
System.out.println(Arrays.toString(fruits));// 2. join() : 連接字符串 (靜態方法)
String result = String.join("-", "apple", "banana", "orange");
// result: "apple-banana-orange"
System.out.println(result);
三、StringBuilder
?/?StringBuffer
?的常用操作
它們的方法幾乎完全一樣,區別在于線程安全。這里以?StringBuilder
?為例。
1. 創建對象
StringBuilder sb = new StringBuilder(); // 默認容量 (16)
StringBuilder sb2 = new StringBuilder("Hello"); // 初始內容
2. 修改字符串(核心功能)
StringBuilder sb = new StringBuilder("Hello");// 1. append() : 追加內容
sb.append(" World");
System.out.println(sb); // "Hello World"// 2. insert() : 在指定位置插入內容
sb.insert(5, ","); // 在索引 5 的位置插入 ","
System.out.println(sb); // "Hello, World"// 3. delete() : 刪除指定區間的內容
sb.delete(5, 7); // 刪除 [5, 7) 區間,即刪除 ", "
System.out.println(sb); // "HelloWorld"// 4. replace() : 替換指定區間的內容
sb.replace(5, 10, " Java"); // 替換 [5, 10) 區間為 " Java"
System.out.println(sb); // "Hello Java"// 5. reverse() : 反轉字符串
sb.reverse();
System.out.println(sb); // "avaJ olleH"// 6. toString() : 轉換為 String 對象
String finalString = sb.toString();
System.out.println(finalString); // "avaJ olleH"
四、性能對比:+
?拼接 vs?StringBuilder
在循環中頻繁使用?+
?拼接字符串是 Java 新手常見的性能陷阱。
1.錯誤示例:使用?+
?拼接
String result = "";
for (int i = 0; i < 10000; i++) {result = result + i; // 每次循環都會創建一個新的 String 對象,性能極差!
}
2.正確示例:使用?StringBuilder
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10000; i++) {sb.append(i); // 在同一個對象上追加,性能極高!
}
String result = sb.toString();
原因分析:
result + i
?的過程實際上是:new StringBuilder().append(result).append(i).toString()
。每次循環都會創建一個?StringBuilder
?和一個新的?String
?對象,導致大量內存浪費和 GC(垃圾回收)壓力。StringBuilder
?的?append
?方法是在一個預先分配好空間的字符數組上進行操作,避免了頻繁創建新對象的開銷。