首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 字符串常用方法實戰大全:concat、replace、substring、大小寫、修剪、性能陷阱與最佳實踐

     編輯:Java 相關知識

前言

`String` 是 Java 使用頻率最高的類,但其**不可變性**導致許多「修改」操作實際創建新對象。掌握核心 API 的正確用法、效能特徵、陷阱 (如 `substring` 內存洩漏歷史問題、`replace` vs `replaceAll` 正則開銷),對寫出高質量代碼至關重要。本文系統整理 10 大常用方法,附帶 JMH 效能對比與最佳實踐。

核心 API 速查表

方法用途返回值關鍵點
`concat(String)`拼接字符串新 String等同 `+`,單次拼接可用;循環拼接**必須用 StringBuilder**
`intern()`進入字符串常量池池中引用手動去重,慎用 (永久代/元空間 OOM 風險),JDK 8+ 池在堆中
`replace(CharSequence, CharSequence)`字面量替換 (全量)新 String**非正則**,效能極高,優先於 `replaceAll`
`replaceAll(String regex, String)`正則替換 (全量)新 String編譯正則開銷大,頻繁調用預編譯 `Pattern`
`replaceFirst(String regex, String)`正則替換 (首次)新 String同 `replaceAll`,僅替換首個匹配
`substring(int begin)`截取尾部新 StringJDK 7+ 複製字符數組,無內存洩漏;JDK 6 共享數組有洩漏
`substring(int begin, int end)`截取範圍新 String左閉右開 `[begin, end)`,越界拋 `StringIndexOutOfBoundsException`
`toLowerCase()` / `toUpperCase()`大小寫轉換新 String默認 Locale.ROOT;指定 Locale 避免土耳其語 I/ı 問題
`trim()`移除首尾空白 (≤ U+0020)新 StringJDK 11+ `strip()` 更強 (Unicode 感知,移除所有空白字符)
`length()`字符數 (char 代碼單元)int非字形簇數;Emoji/補充字符佔 2 個 char,用 `codePointCount` 計真實字符數

實戰代碼演示


public class StringMethodsDemo {
    public static void main(String[] args) {
        String s = "  Hello World!  ";

        // 1. concat (單次可用)
        String s1 = s.concat(" Java");
        System.out.println("concat: '" + s1 + "'");

        // 2. replace (字面量,快)
        String s2 = s1.replace("World", "JVM");
        System.out.println("replace: '" + s2 + "'");

        // 3. replaceAll (正則,慢,慎用於循環)
        String s3 = s2.replaceAll("\\s+", "_"); // 所有空白替換為下劃線
        System.out.println("replaceAll: '" + s3 + "'");

        // 4. replaceFirst
        String s4 = s3.replaceFirst("_", "-");
        System.out.println("replaceFirst: '" + s4 + "'");

        // 5. substring
        String s5 = s4.substring(2); // 從索引 2 到結尾
        String s6 = s4.substring(2, 10); // 索引 2 到 9
        System.out.println("substring(2): '" + s5 + "'");
        System.out.println("substring(2,10): '" + s6 + "'");

        // 6. 大小寫
        String lower = s6.toLowerCase(Locale.ROOT); // 指定 Locale 避免土耳其語問題
        String upper = s6.toUpperCase(Locale.ROOT);
        System.out.println("lower: " + lower + ", upper: " + upper);

        // 7. trim vs strip (JDK 11+)
        String trimmed = s.trim();     // 只移除 ASCII 空白 (空格、制表、換行等 ≤ 0x20)
        String stripped = s.strip();   // 移除所有 Unicode 空白字符 (含全形空格 U+3000 等)
        System.out.println("trim: '" + trimmed + "'");
        System.out.println("strip: '" + stripped + "'");

        // 8. length vs codePointCount
        String emoji = "👍"; // U+1F44D, UTF-16 佔 2 個 char (代理對)
        System.out.println("emoji.length() = " + emoji.length()); // 2
        System.out.println("emoji.codePointCount(0, emoji.length()) = " + emoji.codePointCount(0, emoji.length())); // 1
    }
}

效能深度解析 (JMH 基準測試參考)

1. 拼接:StringBuilder vs + vs concat


// 循環 10000 次拼接
// StringBuilder: ~2 ms (基準)
// + (JDK 9+ 編譯器優化為 StringBuilder): ~3 ms
// concat: ~150 ms (每次創建新對象、複製數組)
// 結論:循環/多次拼接 **強制使用 StringBuilder**

2. 替換:replace (字面量) vs replaceAll (正則)


// 替換 100 萬次 "a" -> "b"
// replace: ~50 ms
// replaceAll: ~1200 ms (每次編譯正則 Pattern)
// 預編譯 Pattern: Pattern p = Pattern.compile("a"); p.matcher(s).replaceAll("b") ~300 ms
// 結論:字面量替換 **優先用 replace**;正則複用 **預編譯 Pattern**

3. substring 歷史內存洩漏 (JDK 6 vs 7+)

  • JDK 6:`substring` 共享原 `char[] value`,只存 `offset`、`count`。長字符串 `substring` 少量字符導致原大數組無法 GC → **嚴重內存洩漏**。
  • JDK 7+:`substring` **複製**新 `char[]` (或 `byte[]` compact strings)。**無洩漏**,但有複製開銷。

最佳實踐總結

  1. 拼接:單次 `+` / `concat` 可讀性好;循環/多次 **`StringBuilder`** (非線程安全,快) 或 `StringBuffer` (線程安全,慢)。
  2. 替換:字面量 **`replace`**;正則 **預編譯 `Pattern`** 複用 `Matcher`;簡單分割 **`split`** (內部用正則,同樣預編譯)。
  3. 大小寫:指定 `Locale.ROOT` 或 `Locale.US` 避免土耳其語 `I/ı` 異常 (`toLowerCase(Locale.ROOT)`)。
  4. 修剪:JDK 11+ **優先 `strip()`** (Unicode 感知);兼容舊版用 `trim()`。
  5. 長度:`length()` 返回 `char` 數 (UTF-16 代碼單元);真實字符數 (字形簇) 用 `codePointCount(0, length())` 或 `String.chars().count()` (流式)。
  6. 比較:內容比較 **`equals()`**;引用比較 `==` (僅常量池/同一對象);忽略大小寫 `equalsIgnoreCase()`。
  7. 常量池:`intern()` 慎用 (元空間壓力);字面量自動入池;動態生成大量去重考慮 `WeakHashMap` 或第三方庫。

總結

Java `String` 方法看似簡單,實則暗藏效能陷阱 (不可變性複製、正則編譯、Unicode 處理、歷史實現差異)。「知其然更知其所以然」:理解 **`replace` 非正則、預編譯 `Pattern`、指定 `Locale`、JDK 11 `strip()`、循環用 `StringBuilder`**,能讓你寫出既正確又高效的字符串處理代碼。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved