核心 API 體系
| 類/方法 | 職責 | 關鍵方法 |
Pattern | 編譯後的正則模式(線程安全) | compile()、matcher()、split() |
Matcher | 匹配引擎(非線程安全) | matches()、find()、group()、replaceAll() |
String | 便捷委托方法 | matches()、split()、replaceAll()、replaceFirst() |
Java 正則元字符速查(雙重轉義陷阱)
關鍵認知:Java 字符串字面量與正則引擎雙層轉義
| 正則意圖 | 正則寫法 | Java 字符串寫法 | 說明 |
匹配點號 . | \. | "\\." | 字符串層轉義反斜槓 |
匹配反斜槓 \ | \\ | "\\\\" | 雙重轉義 |
| 匹配數字 | \d | "\\d" | 等價 [0-9] |
| 匹配非數字 | \D | "\\D" | 等價 [^0-9] |
| 匹配單詞字符 | \w | "\\w" | 等價 [a-zA-Z0-9_] |
| 邊界匹配 | ^ $ \b | "^" "$" "\\b" | 行首/行尾/單詞邊界 |
| 量詞 | * + ? {n,m} | 同 | 貪婪/懶惰/佔有優先 |
實戰場景代碼庫
1. 多重分隔符分割字符串
Pattern pattern = Pattern.compile("[, |]+"); // 逗號、空格、竪線任意組合
String[] parts = pattern.split("Java Hello World Java,Hello,,World|Sun");
// 結果:[Java, Hello, World, Java, Hello, World, Sun]
2. 郵箱格式驗證
String email = "ceponline@yahoo.com.cn";
Pattern pattern = Pattern.compile(".+@.+\\..+"); // 簡化版,生產建議用 RFC 5322 完整規範
boolean valid = pattern.matcher(email).matches(); // true
3. 移除 HTML 標籤
String html = "<a href=\"index.html\">首頁</a>";
String text = Pattern.compile("<.+?>").matcher(html).replaceAll("");
// 結果:首頁
4. 提取 URL
String content = "訪問 <https://www.baidu.com/> 搜索";
Matcher m = Pattern.compile("<https://.+?>").matcher(content);
if (m.find()) {
System.out.println(m.group()); // <https://www.baidu.com/>
}
5. 簡單字符串替換(無需正則)
String str = "正則表達式 Hello World";
String result = str.replace("Hello", "我要替換Hello"); // 普通字符串替換更高效
6. 提取數字(去除非數字字符)
public Double extractNumber(String input) {
String digits = Pattern.compile("[^0-9/.]").matcher(input).replaceAll("");
return Double.parseDouble(digits);
}
// "價格:$1,234.56" → 1234.56
7. 提取字母(去除非字母字符)
public String extractLetters(String input) {
return Pattern.compile("[^a-zA-Z]").matcher(input).replaceAll("").toLowerCase();
}
// "User_Name_123" → "username"
性能優化原則
- 預編譯 Pattern:靜態常量或緩存,避免重複編譯
- 優先用 String 方法:簡單替換/分割用
String.replace/split
- 懶惰量詞:
.+? 避免過度回溯
- 錨點優化:
^pattern$ 限定邊界
- 預編譯標誌位:
Pattern.CASE_INSENSITIVE | Pattern.DOTALL
常見陷阱避雷
matches() = ^pattern$ 全匹配 | find() = 部分匹配
split("|") 按字符分割,需 split("\\|")
- 組引用替換:
$1 在替換字符串中需 "$1" 或 Matcher.quoteReplacement()
- 超長輸入慎用
.* 導致災難性回溯