Definition
Three gotchas:
- Regex argument.
"a.b.c".split(".")returns[]because.is a regex wildcard matching any character. - Trailing empties removed.
"a,,b,".split(",")returns["a", "", "b"](trailing empty dropped). Usesplit(",", -1)to keep them. - Empty string.
"".split(",")returns[""], not an empty array.
split() is like a bank form scanner that uses pattern matching instead of a simple delimiter finder. Tell it to look for a dot and it sees every character as a match. You must escape the dot to mean a literal dot.
Understanding the Concepts
Gotcha 1: split() takes a regex, not a literal
The most common trap is that split() interprets its argument as a regular expression, not a plain string. Regex special characters like ., |, *, +, ?, (, ), [, {, \, ^, and $ have special meaning. A dot matches any single character, so splitting on "." matches every character position and returns an empty array.
"192.168.1.1".split("."); // [] (empty! "." matches any char)
"192.168.1.1".split("\\."); // ["192", "168", "1", "1"] (escaped)
"192.168.1.1".split(Pattern.quote(".")); // ["192", "168", "1", "1"] (safe)
"192.168.1.1".split("[.]"); // ["192", "168", "1", "1"] (character class)
Pattern.quote() is the safest approach because it escapes any special characters automatically. Use it when the delimiter comes from user input or configuration.
Gotcha 2: trailing empty strings are removed by default
By default, split() removes trailing empty strings from the result array. This means if your data has a meaningful empty trailing field, it silently disappears.
"a,,b,".split(","); // ["a", "", "b"] – trailing empty REMOVED!
"a,,b,".split(",", -1); // ["a", "", "b", ""] – trailing empty PRESERVED
In banking CSV processing, a missing trailing field is meaningful. If a transaction record has the format txnId,fromAccount,toAccount,amount,note and the note is empty, the default split drops it. Always use split(delimiter, -1) for data parsing.
package com.bank.service;
public class TransactionParser {
// BAD: loses trailing empty fields
public String[] parseBad(String line) {
return line.split(","); // trailing empties removed!
}
// GOOD: preserves all fields
public String[] parseGood(String line) {
return line.split(",", -1); // trailing empties preserved
}
}
// Example:
String record = "TXN001,SAV2001,CUR3001,50000,";
parseBad(record).length; // 4 (note field is lost!)
parseGood(record).length; // 5 (note field is empty string)
Gotcha 3: splitting an empty string
Splitting an empty string returns an array with one empty element, not an empty array. This trips up length checks.
"".split(","); // [""] (array with one empty element, NOT empty array)
"".split(",").length; // 1 (not 0!)
// To handle this, check the content not just the array
String[] parts = input.split(",", -1);
if (parts.length == 1 && parts[0].isEmpty()) {
// input was empty – handle accordingly
}
When to use a proper CSV library
split() cannot handle quoted fields, which are standard in CSV. A field value containing the delimiter breaks the parse.
// BAD: split does not handle quoted fields
String line = "Rajesh,\"National Bank, Mumbai\",500000";
line.split(","); // ["Rajesh", "\"National Bank", " Mumbai\"", "500000"] (broken!)
// GOOD: use OpenCSV or Apache Commons CSV
import com.opencsv.CSVReader;
import com.opencsv.CSVReaderBuilder;
import java.io.StringReader;
CSVReader reader = new CSVReaderBuilder(new StringReader(line)).build();
String[] fields = reader.readNext(); // ["Rajesh", "National Bank, Mumbai", "500000"]
In banking applications at National Bank of India, Rajesh uses Apache Commons CSV for all file parsing because transaction descriptions often contain commas, quotes, and newlines.
What about the limit parameter?
split(regex, limit) controls how many parts to produce:
| Limit value | Behavior |
|---|---|
| 0 (default) | Remove trailing empties, no limit on count |
| -1 | Keep trailing empties, no limit on count |
| n (positive) | At most n parts; last part contains the remainder |
"a,b,c,d".split(",", 2); // ["a", "b,c,d"] – split into exactly 2 parts
"a,b,c,d".split(",", -1); // ["a", "b", "c", "d"] – all parts preserved
What should a senior engineer know?
- Pattern.compile() and reuse for repeated splits:
Pattern.compile(",").split(line)avoids recompiling the regex each time in a hot loop. - In Java 8+, use streams for complex tokenization:
Pattern.compile(",").splitAsStream(line).map(String::trim).toList(). - For simple single-character delimiters, some libraries provide non-regex split methods that are faster. Guava's
Splitter.on(',').splitToList(line)is explicit and avoids regex pitfalls.
Visual Overview
split(".") → regex: . = any char → matches everything → empty result
split("\\\\.") → escaped: literal dot → correct
split(",") → trailing empties removed
split(",", -1) → trailing empties preserved
"".split(",") → [""] (not empty array)
For CSV: use a library (OpenCSV, Commons CSV) not split()
Key Takeaway
String.split() takes a regex, not a plain string. Dot, pipe, and other regex characters must be escaped. Trailing empty strings are removed by default – use limit=-1 to preserve them. And for real CSV parsing, use a proper library instead of split.
One sentence to remember: split() is regex-based – escape special characters, use -1 limit to keep trailing empties, and use a CSV library for real data.
---