String.split(String regex, int limit) 是字串切割的核心方法,但其正則表達式參數與 limit 參數行為常導致困惑。本文系統講解切割邏輯、limit 三種模式、特殊字元轉義、效能優化與常見錯誤案例。
public String[] split(String regex) // 等同 limit=0
public String[] split(String regex, int limit)
regex:正則表達式,非純字串。特殊字元需轉義(如 \\.、\\|、\\$)。limit:控制切割次數與尾部空串保留行為,三種模式差異巨大。
String src = "boo:and:foo";
src.split(":", 2) // limit=2 → 切 1 次
// 結果:["boo", "and:foo"] 長度=2
src.split(":", 3) // 切 2 次
// 結果:["boo", "and", "foo"] 長度=3
"boo:and:foo".split(":", -1)
// 結果:["boo", "and", "foo"] 長度=3
"boo:and:foo:".split(":", -1) // 結尾有分隔符
// 結果:["boo", "and", "foo", ""] 長度=4(保留尾部空串)
"oo".split("o", -1) // 分隔符在首尾
// 結果:["", "", ""] 長度=3
"boo:and:foo".split(":", 0)
// 結果:["boo", "and", "foo"] 長度=3
"boo:and:foo:".split(":", 0) // 結尾空串被丟棄
// 結果:["boo", "and", "foo"] 長度=3
"oo".split("o", 0) // 所有空串被丟棄
// 結果:[] 長度=0 ⚠️ 易導致邏輯錯誤
| 輸入字串 | regex | limit > 0 (如 3) | limit < 0 (如 -1) | limit = 0 (預設) |
|---|---|---|---|---|
| a:b:c | : | [a, b, c] | [a, b, c] | [a, b, c] |
| a:b:c: | : | [a, b, c:] | [a, b, c, ""] | [a, b, c] |
| :a:b | : | ["", a, b:] | ["", a, b] | ["", a, b] |
| aaa | a | ["", "", "", ""] | ["", "", "", ""] | [] |
正則元字元:. | $ ^ * + ? { } [ ] ( ) \
// 切割 "1.2.3" 按點
"1.2.3".split("\\."); // 正確:["1", "2", "3"]
"1.2.3".split("."); // 錯誤:. 匹配任意字元 → ["", "", "", "", ""]
// 切割 "a|b|c" 按管道符
"a|b|c".split("\\|"); // 正確
// 切割 Windows 路徑 "C:\\Users"
path.split("\\\\"); // 正則需 \\\\,Java 字串再轉義 → 實際傳給引擎 \\
技巧:Java 14+ 可用 Pattern.quote(str) 自動轉義整段字串:src.split(Pattern.quote("."))。
private static final Pattern COLON_PATTERN = Pattern.compile(":");
// 使用
COLON_PATTERN.split(input, limit);
| 錯誤代碼 | 問題 | 修正 |
|---|---|---|
| str.split("|") | | 為或運算,匹配空字串 → 每字元拆分 | str.split("\\|") |
| str.split(".") | . 匹配任意字元 | str.split("\\.") 或 Pattern.quote(".") |
| csv.split(",") | 未處理引號內逗號、換行 | 用專用 CSV 解析庫 |
| limit=0 導致尾部空串丟失 | 解析 "a,b,c," 少最後一欄 | 用 limit=-1 保留空串 |
// 直接傳 Pattern 物件,避免字串轉義麻煩
String[] parts = src.split(Pattern.compile(":"));
// 配合 lines() 處理多行文本
String multi = "line1\nline2\nline3";
List lines = multi.lines().collect(Collectors.toList());
Pattern.quote() 或預編譯 Pattern。limit=-1**。split,改用手寫解析或專用庫。FileSystems.getDefault().getSeparator() 而非硬編碼。