Use s.split(","), which returns a String[]: "java,kotlin,scala".split(",") gives [java, kotlin, scala]. The separator is a regular expression, so escape ., | and $ (split("\\.")) or wrap it in Pattern.quote(sep). For a List, wrap the result: Arrays.asList(s.split(",")).
String.split is the answer, and it has three behaviours that surprise almost everyone the first time. The argument is a regex, not plain text, so split(".") returns an empty array. Empty strings at the end of the result are silently removed unless you pass a limit. And splitting on a single space falls apart the moment the input has two spaces or a tab. This page covers all three with real output, then turns the pieces into a List, compares the legacy StringTokenizer, and ends with a table. Each example runs on this page: hit Run, then edit the code and run it again.
1String.split()Recommended
s.split(regex) cuts the string at every match of the separator and returns the pieces as a String[]. The separator can be more than one character, and the original string is untouched, because Java strings are immutable. Print the array with Arrays.toString; printing the array directly shows its type and a hash, not the contents (see printing an array).
Output
Prints [java, kotlin, scala] 3 and java scala, then [a, b, c] for the multi-character separator. When the separator isn't found you get the whole input back as one element, [nope] 1. The empty-input line is the one to remember: [] 1. It looks empty, but the array holds one empty string (the last line prints true for empty[0].isEmpty()), so parts.length == 0 does not mean "no input". Check s.isEmpty() before splitting instead.
2The separator is a regex: escaping ., | and $
The parameter of split is named regex for a reason. A comma or a semicolon means itself, but . means "any character", | means "or" and $ means "end of input", and each one produces a silently wrong result instead of an error. Escape the character with a backslash (written \\ in a Java string literal), put it in a character class like [.], or let Pattern.quote do the escaping for you.
Output
"25.0.3".split(".") has length 0: every character matched as a separator, every piece between them was empty, and trailing empties are dropped (section 3), which here means all of them. Escaped or in a class, it prints [25, 0, 3]. An unescaped pipe splits between every character, [r, e, d, |, g, r, e, e, n], and "$" never matches inside the string, so you get [10$20$30] back unchanged. Pattern.quote("$") returns \Q$\E, regex syntax for "everything between is literal", and splits correctly into [10, 20, 30]. The last line shows the useful side of regex: [;,|] splits on any of three delimiters at once, giving [a, b, c, d]. Splitting on a single ordinary character such as , skips the regex engine entirely, so there is no speed penalty for the common case.
3Trailing empty strings and the limit argument
One-argument split(regex) is split(regex, 0), and a limit of 0 removes empty strings from the end of the result. Empty strings at the start and in the middle stay. The second argument changes that: a negative limit keeps everything, and a positive limit n stops after n pieces, leaving the rest of the string, separators and all, in the last one. This snippet prints each piece in quotes so the empty ones are visible.
Output
With the default limit, "ada,,london,," gives ["ada", "", "london"] 3: the middle empty survives, the two trailing ones are gone. With -1 all five pieces come back. A leading empty is always kept (["", "a", "b"] 3), and a string of nothing but commas gives [] 0, because every piece is a trailing one. For rows of fixed columns, always pass -1, or a blank last column quietly shortens the array and parts[4] throws ArrayIndexOutOfBoundsException. A limit of 2 is how you split exactly once: url -> https://x.io/?q=1 keeps the = inside the value, where a plain split("=") cuts the URL into three pieces. If the separator is missing, a limit-2 split returns one element, so check kv.length == 2 before reading kv[1].
4Splitting on whitespace: "\\s+" and strip()
Splitting a sentence with split(" ") is the classic bug. Two spaces in a row make an empty piece, a tab isn't a separator at all, and leading spaces add empties at the front. The regex "\\s+" matches any run of whitespace, which fixes the middle, but a leading run still leaves one empty string in front. Call strip() (Java 11+) or trim() first, then split.
Output
split(" ") returns six pieces, four of them empty, with the tab and newline still inside "it\tnow\n". split("\\s+") gets the words but starts with an empty string, ["", "ship", "it", "now"] 4, and only strip() plus "\\s+" gives the clean ["ship", "it", "now"] 3. There is no trailing empty in the second line because trailing empties are dropped anyway. Blank input is the last trap: it strips to "", which splits to [""] 1, so guard with isBlank() (Java 11+) if zero words should mean an empty array. strip() removes Unicode whitespace, while trim() only removes characters up to U+0020; for ordinary ASCII input they give the same result.
5Into a List: Arrays.asList, List.of and streams
split returns an array, and the second most-asked version of this question is how to get a List instead. Arrays.asList wraps the array without copying it, List.of (Java 9+) makes an unmodifiable copy, and a stream lets you clean each piece on the way. Pattern.splitAsStream skips the array altogether and is the natural choice when you split with the same regex many times, since the pattern is compiled once. For more on the array-to-list step, see converting an array to a list.
Output
Arrays.asList prints [red, green, blue] but refuses to grow: add failed: UnsupportedOperationException. It is a fixed-size view of the array (set works, add and remove don't), so copy it into an ArrayList when you need to change its size, which gives [red, green, blue, cyan]. The stream turns the messy " red, green ,blue, ," into a clean [red, green, blue], and the "\\s*,\\s*" regex removes the spaces around each comma in one call, though not blank entries or spaces at the very ends. splitAsStream feeds straight into map(Integer::valueOf), giving [3, 1, 4, 1, 5] and a sum of 14. Parsing each piece is covered in converting a String to an int, and the reverse trip in joining a list into a string.
6split() vs StringTokenizer (legacy)
Older code and old answers use java.util.StringTokenizer. It predates regex support in Java, and its documentation calls it "a legacy class that is retained for compatibility reasons although its use is discouraged in new code". It still works, but it differs from split in two ways that matter: its delimiter argument is a set of single characters, not a pattern, and it skips empty tokens without telling you.
Output
The tokenizer reports 3 tokens, ada, london and 1815, and the blank second field has vanished, so you can no longer tell which column was which. split("[,;]") returns [ada, , london, 1815] 4 with the empty field in place. With no delimiter argument, the tokenizer splits on whitespace and finds 3 words in " ship it\tnow\n", the same as strip().split("\\s+") in section 4. In new code, use split or Pattern.
7Which should you use?
| Method | Empty pieces | Returns | Best for |
|---|---|---|---|
| s.split(",") | Trailing ones dropped | String[] | A known separator: the default |
| s.split(",", -1) | All kept | String[] | Rows with a fixed number of columns |
| s.split("=", 2) | At most 2 pieces | String[] | key=value, splitting once |
| s.split(Pattern.quote(sep)) | Trailing ones dropped | String[] | A separator in a variable |
| s.strip().split("\\s+") | None (unless blank) | String[] | Words separated by whitespace |
| Arrays.stream(s.split(",")).map(String::trim) | Filter them out | List<String> | Comma lists with stray spaces |
| Pattern.compile(re).splitAsStream(s) | Trailing ones dropped | Stream<String> | A reused regex, stream pipelines |
| new StringTokenizer(s, ",") | Always skipped | Tokens one by one | Legacy code only |
Frequently asked questions
How do I split a string on a dot or a pipe in Java?
Escape it, because split takes a regular expression: . means "any character" and | means "or", so "25.0.3".split(".") returns an array of length 0. Write split("\\.") or split("\\|") (two backslashes in Java source), use a character class such as split("[.]"), or wrap the separator with Pattern.quote("."), which is the safe choice when it comes from a variable. A backslash separator needs four in source: "C:\\dev\\tools".split("\\\\") gives [C:, dev, tools].
Why does split() remove the empty strings at the end?
Because split(regex) is split(regex, 0), and a limit of 0 drops trailing empty strings. Empty strings at the start and in the middle are kept, so "ada,,london,,".split(",") has 3 elements. Pass a negative limit to keep every piece: "ada,,london,,".split(",", -1) has 5. Use -1 for CSV-style rows, where a blank last column would otherwise shorten the array.
How do I convert a comma-separated String to a List in Java?
Split it and wrap the array: Arrays.asList(s.split("\\s*,\\s*")), where the regex also swallows spaces around each comma. That list is fixed-size, so add throws UnsupportedOperationException; copy it with new ArrayList<>(...) if you need to change it, or use List.of(s.split(",")) (Java 9+) for an unmodifiable one. To trim each piece and drop blanks, stream it: Arrays.stream(s.split(",")).map(String::trim).filter(x -> !x.isEmpty()).toList() (toList() is Java 16+). Outside plain Java SE, Guava's Splitter does the same job.
How do I split a string into lines in Java?
Use text.lines() (Java 11+), which returns a Stream<String> and understands \n, \r\n and \r, or text.split("\\R") (Java 8+) for an array, since \R is the regex for any line break. Both turn "a\r\nb\nc\n" into [a, b, c]. Splitting on "\n" alone leaves a carriage return on each Windows line, giving [a\r, b, c].
How do I split a string into characters in Java?
"abc".split("") returns [a, b, c] (since Java 8 there is no leading empty string), and s.toCharArray() gives char values. Both work in UTF-16 code units, so an emoji is cut into two halves: "a😀b".split("") has 4 elements. For whole characters use s.codePoints().mapToObj(Character::toString).toList() (Java 16+ for toList()), which gives [a, 😀, b].
Should I use split() or StringTokenizer?
Use split or Pattern in new code. The JDK documentation calls StringTokenizer a legacy class whose use is discouraged. It treats its delimiter string as a set of single characters, cannot take a regex, and silently skips empty tokens: new StringTokenizer("ada,,london;1815", ",;") yields 3 tokens, while "ada,,london;1815".split("[,;]") returns 4 pieces with the blank field in place.