How does the limit argument to String.split (and Pattern.split) work, and what is the default trailing-empty-string behavior?
answer
- limit 0 (default) drops TRAILING empties
- limit < 0 (-1) keeps ALL trailing empties
- limit > 0 caps pieces at n, last holds the remainder
- Leading/interior empties always kept
- CSV fix: split(",", -1)
basics
~20 ssplit(regex) with no limit (or limit 0) removes trailing empty strings. A positive limit caps the number of pieces and keeps trailing empties; a negative limit keeps ALL trailing empties with no cap. Limit 0 is the default and the source of most surprises.
solid answer
~50 ssplit takes an optional limit that controls how many times the pattern is applied and how trailing empty strings are handled. With a positive limit n, the pattern is applied at most n-1 times, so the array has at most n elements and the last element keeps the unsplit remainder; trailing empties are preserved. With limit 0 (the default for the one-arg split), the pattern is applied as many times as possible, but trailing empty strings are discarded — so "a,b,,".split(",") yields [a, b], not [a, b, "", ""]. With a negative limit, the pattern is applied as many times as possible AND all trailing empties are kept. The classic bug is losing trailing empty fields when parsing CSV-like data; pass a negative limit (commonly -1) to keep every field. Leading and interior empties are always kept regardless of limit.
go deeper
Knows split breaks a string on a delimiter and returns an array.
Knows the default drops trailing empties and that a limit argument exists to change behavior.
Articulates all three regimes (0 drops trailing, negative keeps all, positive caps with remainder) and reaches for -1 to avoid the CSV trailing-field bug.
Anticipates data-integrity bugs from dropped fields across the codebase, sets parsing conventions, and weighs split vs a real CSV parser and precompiled Pattern for performance.
## What split does `String.split(String regex)` and `String.split(String regex, int limit)` (and the equivalent `Pattern.split`) break a string into an array of substrings around matches of the regex. The optional **limit** controls two things: how many splits happen, and whether **trailing empty strings** survive. An **empty string** appears in the result when two delimiters are adjacent, or a delimiter sits at the start/end. "Trailing" empties are the ones at the **end** of the array. ## The three limit regimes Let `n = limit`. ### 1. `limit > 0` (e.g. 2, 3) - The pattern is applied **at most n-1 times**. - The array has **at most n** elements. - The **last** element is the entire remaining unsplit text (so it can contain delimiters). - Trailing empty strings **are kept**. ```java "a:b:c:d".split(":", 2); // ["a", "b:c:d"] "a:b:c:".split(":", 2); // ["a", "b:c:"] ``` ### 2. `limit == 0` (this is what one-arg `split` uses) - The pattern is applied **as many times as possible** (no cap). - **Trailing empty strings are removed.** ```java "a,b,,".split(","); // ["a", "b"] <-- two trailing empties dropped "a,b,,".split(",", 0); // same: ["a", "b"] ``` ### 3. `limit < 0` (e.g. -1) - The pattern is applied **as many times as possible** (no cap). - **All trailing empty strings are kept.** ```java "a,b,,".split(",", -1); // ["a", "b", "", ""] ``` ## Important nuances - **Only TRAILING empties are affected by limit 0.** Leading and interior empties are always preserved: `",a,,b".split(",")` → `["", "a", "", "b"]`. - **A leading match still produces a leading empty string** — except `split` has one special case: if the regex does not match a zero-width at the very start... in practice, a delimiter at position 0 yields an initial empty element (e.g. `":a".split(":")` → `["", "a"]`). - **A string with no match** returns a single-element array containing the whole original string. - The empty string `""` split by any pattern returns `[""]` (one empty element). ## Why this matters — the CSV bug Parsing `"alice,,bob,"` (a missing middle field and an empty trailing field) with `split(",")` gives `["alice", "", "bob"]` — the trailing empty field is silently lost, so a positional parser misaligns columns. Use `split(",", -1)` → `["alice", "", "bob", ""]` to preserve every field. ## Performance / API notes - `String.split` recompiles the regex each call; for a hot loop, `Pattern.compile(...).split(...)` reuses the compiled pattern. - For single-character literal delimiters, the JDK fast-paths `split`, but a metacharacter like `.` or `|` still needs `Pattern.quote`.
- What does "boo:and:foo".split(":", -2) return?Any negative limit behaves the same: no cap and keep trailing empties. Result: ["boo", "and", "foo"]. The exact negative value does not matter.
- How would you parse a tab-separated line keeping empty trailing columns?line.split("\t", -1), so trailing empty columns are preserved and positional indexing stays aligned.
saying these in an interview costs you the question
- Assuming default split keeps trailing empty fields
- Thinking limit 0 and limit -1 behave the same
- Believing limit affects leading/interior empties (only trailing)
- Expecting positive limit to keep splitting after n-1 cuts