Back to String & String Pool
Q12Question 12 of 12

What are the gotchas of String.split()?

Key Concepts
  • split() takes a REGEX, not a plain string – "." matches any character, not a literal dot
  • Use Pattern.quote(".") or "[.]" or \\\\. to match a literal dot
  • Trailing empty strings are removed by default – split("delimiter", -1) preserves them
  • Splitting an empty string returns [""] (array with one empty element), not an empty array
  • For CSV parsing, use a proper CSV library (OpenCSV, Apache Commons CSV) instead of split()

Definition

split() takes a regex, not a literal. "." matches anything. Trailing empties are removed. Use Pattern.quote() for literal delimiters.

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). Use split(",", -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.

JAVA
"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.

JAVA
"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.

JAVA
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.

JAVA
"".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.

JAVA
// 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 |

JAVA
"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

DIAGRAM
  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.

---

Share
Use ← → arrow keys to navigate