Learn every Groovy split string method with 12 tested examples. Split by comma, regex, limit, and more. Complete guide for Groovy 5.x.
“Splitting a string sounds trivial until you hit the edge cases. Then it becomes the most important string method in your toolkit.”
Larry Wall, Programming Perl
Last Updated: March 2026 | Tested on: Groovy 5.x, Java 17+ | Difficulty: Beginner to Intermediate | Reading Time: 16 minutes
If you’ve ever parsed a CSV file, read command output, or processed user input in Groovy, you’ve used split(). It’s one of those methods you reach for almost daily – and yet there’s a surprising amount of depth to it once you start looking at regex patterns, limits, and edge cases.
This post is your complete guide to Groovy split string operations. We’ll walk through 12 tested examples covering everything from basic comma splitting to regex-powered parsing, CSV handling, multiline splitting, and the important differences between split() and tokenize(). If you haven’t already, check out our Groovy String Tutorial for the foundations, and our dedicated tokenize() guide for the other side of this coin.
Every example here is tested on Groovy 5.x with exact output shown. Let’s get into it.
Table of Contents
How split() Works in Groovy
The split() method in Groovy comes from Java’s java.lang.String. It takes a regular expression pattern and breaks the string into a String[] array wherever that pattern matches. This is important to remember – the argument is always treated as a regex, even if it looks like a plain string.
According to the Groovy GDK documentation, Groovy also adds its own split() overload (no arguments) that splits on whitespace. So you get the best of both worlds – Java’s regex-powered splitting plus Groovy’s convenience methods.
Key Points:
split()returns aString[](Java array), not a Groovy List- The delimiter is a regex pattern, not a literal string
- Empty trailing elements are removed by default
- Use
split(regex, -1)to keep all empty elements including trailing ones - Groovy’s no-arg
split()splits on any whitespace - For literal delimiters, consider
tokenize()instead – it’s simpler and returns a List
Syntax and Method Signatures
| Method | Source | Returns | Description |
|---|---|---|---|
split() | Groovy GDK | String[] | Split on whitespace |
split(String regex) | Java String | String[] | Split on regex pattern |
split(String regex, int limit) | Java String | String[] | Split on regex with max parts |
split() Method Signatures
// Groovy GDK - no arguments, splits on whitespace
String[] result1 = "Hello World Groovy".split()
// Java String - regex pattern
String[] result2 = "a,b,c".split(",")
// Java String - regex with limit
String[] result3 = "a,b,c,d,e".split(",", 3)
println result1 as List // [Hello, World, Groovy]
println result2 as List // [a, b, c]
println result3 as List // [a, b, c,d,e]
Output
[Hello, World, Groovy] [a, b, c] [a, b, c,d,e]
Notice how we use as List to print the array in a readable format. Without it, you’d see [Ljava.lang.String;@1a2b3c – the raw array’s toString() output.
12 Practical Split Examples
Example 1: Basic split() – Split by Comma
What we’re doing: The most common use case – splitting a comma-separated string into individual values.
Example 1: Split by Comma
def fruits = "apple,banana,cherry,date"
def parts = fruits.split(",")
println "Type: ${parts.getClass().name}"
println "Length: ${parts.length}"
println "Parts: ${parts as List}"
println "First: ${parts[0]}"
println "Last: ${parts[-1]}"
Output
Type: [Ljava.lang.String; Length: 4 Parts: [apple, banana, cherry, date] First: apple Last: date
What happened here: The split(",") call breaks the string at every comma and returns a String[]. The type name [Ljava.lang.String; is Java’s internal representation of a String array. Groovy lets you access elements with negative indices just like a List – parts[-1] gives the last element.
Example 2: Split with Regex Pattern
What we’re doing: Using a regex pattern to split on multiple possible delimiters at once.
Example 2: Split with Regex
def data = "apple;banana,cherry:date|elderberry"
// Split on any of ; , : or |
def parts = data.split(/[;,:|]/)
println "Parts: ${parts as List}"
// Split on one or more digits
def mixed = "hello123world456groovy"
def words = mixed.split(/\d+/)
println "Words: ${words as List}"
// Split on any non-alphanumeric character
def messy = "one--two..three//four"
def clean = messy.split(/[^a-zA-Z0-9]+/)
println "Clean: ${clean as List}"
Output
Parts: [apple, banana, cherry, date, elderberry] Words: [hello, world, groovy] Clean: [one, two, three, four]
What happened here: Because split() takes a regex, you can use character classes like [;,:|] to match any of several delimiters. The slashy string syntax /pattern/ makes regex patterns cleaner since you don’t need to double-escape backslashes. This is one of Groovy’s biggest wins over Java for regex work.
Example 3: Split with Limit Parameter
What we’re doing: Controlling how many pieces the string is split into using the limit parameter.
Example 3: Split with Limit
def path = "com.technoscripts.groovy.utils.StringHelper"
// No limit - splits into all parts
println "All: ${path.split(/\./) as List}"
// Limit 2 - splits into exactly 2 parts
println "Limit 2: ${path.split(/\./, 2) as List}"
// Limit 3 - splits into at most 3 parts
println "Limit 3: ${path.split(/\./, 3) as List}"
// Practical: split on first occurrence only
def keyValue = "name=John=Doe=Jr"
def (key, value) = keyValue.split("=", 2)
println "Key: ${key}"
println "Value: ${value}"
Output
All: [com, technoscripts, groovy, utils, StringHelper] Limit 2: [com, technoscripts.groovy.utils.StringHelper] Limit 3: [com, technoscripts, groovy.utils.StringHelper] Key: name Value: John=Doe=Jr
What happened here: The limit parameter tells split() the maximum number of pieces to produce. Once it reaches that count, it stops splitting and puts everything remaining into the last element. The key-value example is especially useful – split("=", 2) splits only on the first =, so values containing = stay intact. Notice the Groovy destructuring assignment – def (key, value) = ... unpacks the array directly into variables.
Example 4: Split by Whitespace
What we’re doing: Splitting strings by various types of whitespace – spaces, tabs, newlines, and multiple spaces.
Example 4: Split by Whitespace
// Groovy's no-arg split() handles all whitespace
def spaced = " Hello World Groovy "
println "No-arg: ${spaced.split() as List}"
// Explicit regex for whitespace
def tabbed = "Alice\tBob\tCharlie"
println "Tabs: ${tabbed.split(/\t/) as List}"
// Mixed whitespace - spaces, tabs, newlines
def mixed = "one two\tthree\nfour\r\nfive"
println "Mixed: ${mixed.split(/\s+/) as List}"
// Split on exactly one space (not multiple)
def singles = "a b c d"
println "Single space: ${singles.split(' ') as List}"
println "Multi space: ${singles.split(/\s+/) as List}"
Output
No-arg: [Hello, World, Groovy] Tabs: [Alice, Bob, Charlie] Mixed: [one, two, three, four, five] Single space: [a, b, , c, , , d] Multi space: [a, b, c, d]
What happened here: Groovy’s no-arg split() is smart – it trims leading and trailing whitespace and splits on any whitespace run. When you use split(' ') with a literal space, consecutive spaces produce empty strings. Use /\s+/ to match one-or-more whitespace characters and avoid those empties.
Example 5: Split and Collect/Transform
What we’re doing: Splitting a string and immediately transforming the pieces using Groovy’s collection methods.
Example 5: Split and Transform
def csv = " apple , BANANA , Cherry , date "
// Split, trim, and lowercase in one chain
def cleaned = csv.split(",")
.collect { it.trim().toLowerCase() }
println "Cleaned: ${cleaned}"
// Split and filter
def numbers = "1,2,,3,,4,5,,"
def valid = numbers.split(",")
.findAll { it.trim() }
.collect { it.toInteger() }
println "Valid numbers: ${valid}"
println "Sum: ${valid.sum()}"
// Split and create a map
def config = "host=localhost,port=8080,debug=true"
def settings = config.split(",")
.collectEntries { entry ->
def (k, v) = entry.split("=", 2)
[k, v]
}
println "Settings: ${settings}"
println "Host: ${settings.host}"
Output
Cleaned: [apple, banana, cherry, date] Valid numbers: [1, 2, 3, 4, 5] Sum: 15 Settings: [host:localhost, port:8080, debug:true] Host: localhost
What happened here: This is where Groovy really shines. Even though split() returns a Java array, Groovy lets you call collect(), findAll(), and collectEntries() on it thanks to the GDK. The config-to-map pattern – split on comma, then split each entry on equals – is something you’ll use constantly in real projects.
Example 6: Splitting CSV Data Properly
What we’re doing: Handling CSV data where values may contain commas inside quoted fields.
Example 6: CSV Parsing
// Simple CSV - no quoted fields
def simpleCsv = "John,30,New York,Engineer"
def fields = simpleCsv.split(",")
println "Simple: ${fields as List}"
// CSV with quoted fields containing commas
// For this, split() alone isn't enough - use regex
def complexCsv = 'John,"Doe, Jr.",30,"New York, NY"'
def pattern = /,(?=(?:[^"]*"[^"]*")*[^"]*$)/
def complexFields = complexCsv.split(pattern)
.collect { it.replaceAll(/^"|"$/, '') }
println "Complex: ${complexFields as List}"
// Multi-row CSV processing
def csvData = """name,age,city
Alice,28,London
Bob,35,Paris
Charlie,42,Tokyo"""
def rows = csvData.split("\n")
def headers = rows[0].split(",")
def records = rows[1..-1].collect { row ->
def values = row.split(",")
[headers, values].transpose().collectEntries()
}
println "Headers: ${headers as List}"
records.each { println it }
Output
Simple: [John, 30, New York, Engineer] Complex: [John, Doe, Jr., 30, New York, NY] Headers: [name, age, city] [name:Alice, age:28, city:London] [name:Bob, age:35, city:Paris] [name:Charlie, age:42, city:Tokyo]
What happened here: Simple CSV parsing with split(",") works fine when fields don’t contain commas. For quoted fields, we use a regex lookahead that only matches commas outside quotes. The multi-row example shows a pattern for converting CSV into a list of maps – transpose() pairs headers with values, and collectEntries() turns each pair into a map entry. For production CSV parsing, consider using a library like OpenCSV.
Example 7: Splitting Multiline Strings
What we’re doing: Breaking multiline text into individual lines, handling different line ending styles.
Example 7: Multiline Split
def text = """Line one
Line two
Line three
Line four"""
// Split on newline
def lines = text.split("\n")
println "Lines: ${lines.length}"
lines.eachWithIndex { line, i ->
println " ${i + 1}: ${line}"
}
// Handle Windows \r\n and Unix \n line endings
def mixedEndings = "Windows\r\nUnix\nOld Mac\rDone"
def allLines = mixedEndings.split(/\r?\n|\r/)
println "\nMixed endings: ${allLines as List}"
// Split into paragraphs (separated by blank lines)
def article = """First paragraph content here.
Second paragraph starts after blank line.
Third paragraph is the last one."""
def paragraphs = article.split(/\n\n+/)
println "\nParagraphs: ${paragraphs.length}"
paragraphs.eachWithIndex { p, i ->
println " P${i + 1}: ${p.take(40)}..."
}
Output
Lines: 4 1: Line one 2: Line two 3: Line three 4: Line four Mixed endings: [Windows, Unix, Old Mac, Done] Paragraphs: 3 P1: First paragraph content here.... P2: Second paragraph starts after blank line... P3: Third paragraph is the last one....
What happened here: When splitting by lines, watch out for platform differences. Windows uses \r\n, Unix uses \n, and old Mac used \r. The regex /\r?\n|\r/ handles all three. Splitting on /\n\n+/ breaks text into paragraphs by matching one or more consecutive blank lines. You can also use Groovy’s readLines() method as an alternative for line splitting.
Example 8: Splitting into Pairs and Chunks
What we’re doing: Splitting a string and then grouping the results into pairs or fixed-size chunks.
Example 8: Split into Pairs
// Split into key-value pairs
def params = "name=Alice&age=30&city=London&role=admin"
def pairs = params.split("&").collect { it.split("=", 2) }
println "Pairs: ${pairs}"
// Convert to map
def map = params.split("&").collectEntries {
def (k, v) = it.split("=", 2)
[k, v]
}
println "Map: ${map}"
// Split and group into chunks of 3
def items = "a,b,c,d,e,f,g,h,i"
def chunks = items.split(",").toList().collate(3)
println "Chunks of 3: ${chunks}"
// Split and create pairs (sliding window)
def sequence = "1,2,3,4,5"
def elements = sequence.split(",")
def slidingPairs = (0..<elements.length - 1).collect { i ->
[elements[i], elements[i + 1]]
}
println "Sliding pairs: ${slidingPairs}"
Output
Pairs: [[name, Alice], [age, 30], [city, London], [role, admin]] Map: [name:Alice, age:30, city:London, role:admin] Chunks of 3: [[a, b, c], [d, e, f], [g, h, i]] Sliding pairs: [[1, 2], [2, 3], [3, 4], [4, 5]]
What happened here: The query string parsing pattern is something you’ll see in web applications all the time. Notice we use split("=", 2) with a limit of 2 to handle values that might contain =. The collate(3) method groups a list into sublists of the specified size – very handy for batch processing. The sliding window pattern is useful for finding adjacent pairs in sequential data.
Example 9: Split and Rejoin
What we’re doing: Splitting a string, transforming it, and joining it back together – a common pattern for text reformatting.
Example 9: Split and Rejoin
// Convert CSV to tab-separated
def csv = "Alice,30,London"
def tsv = csv.split(",").join("\t")
println "TSV: ${tsv}"
// Reverse word order
def sentence = "Groovy is awesome"
def reversed = sentence.split(/\s+/).reverse().join(" ")
println "Reversed: ${reversed}"
// CamelCase to snake_case
def camelCase = "myVariableName"
def snakeCase = camelCase.split(/(?=[A-Z])/)
.collect { it.toLowerCase() }
.join("_")
println "Snake: ${snakeCase}"
// Capitalize each word (title case)
def title = "the quick brown fox"
def titleCase = title.split(/\s+/)
.collect { it.capitalize() }
.join(" ")
println "Title: ${titleCase}"
// Filter and rejoin
def tags = "groovy, , java, , kotlin, , scala"
def cleanTags = tags.split(",")
.collect { it.trim() }
.findAll { it }
.join(", ")
println "Clean tags: ${cleanTags}"
Output
TSV: Alice 30 London Reversed: awesome is Groovy Snake: my_variable_name Title: The Quick Brown Fox Clean tags: groovy, java, kotlin, scala
What happened here: The split-transform-join pattern is incredibly versatile. The camelCase to snake_case conversion uses a clever regex – /(?=[A-Z])/ is a zero-width lookahead that splits before each uppercase letter without consuming it. Groovy’s capitalize() method uppercases the first letter and lowercases the rest, making title case conversion a breeze.
Example 10: Handling Edge Cases – Empty and Null Strings
What we’re doing: Understanding how split() behaves with empty strings, trailing delimiters, and null values.
Example 10: Edge Cases
// Empty string
def empty = ""
println "Empty split: ${empty.split(',') as List} (length: ${empty.split(',').length})"
// Trailing delimiters - default behavior removes trailing empties
def trailing = "a,b,c,,,"
println "Default: ${trailing.split(',') as List}"
// Limit -1 keeps ALL empty elements including trailing
println "Limit -1: ${trailing.split(',', -1) as List}"
// Leading delimiter creates leading empty element
def leading = ",a,b,c"
println "Leading: ${leading.split(',') as List}"
// Only delimiters
def onlyCommas = ",,,"
println "Only commas: ${onlyCommas.split(',') as List}"
println "Only commas -1: ${onlyCommas.split(',', -1) as List}"
// Null safety with Groovy's safe navigation
String nullStr = null
println "Null safe: ${nullStr?.split(',')}"
// Single element (no delimiter found)
def single = "hello"
def singleParts = single.split(",")
println "Single: ${singleParts as List} (length: ${singleParts.length})"
Output
Empty split: [] (length: 1) Default: [a, b, c] Limit -1: [a, b, c, , , ] Leading: [, a, b, c] Only commas: [] Only commas -1: [, , , ] Null safe: null Single: [hello] (length: 1)
What happened here: This is where split() surprises people. By default, trailing empty strings are removed. So "a,b,c,,," splits into just [a, b, c]. If you need those trailing empties preserved (common in fixed-format data), pass -1 as the limit. Leading empty elements are always preserved. And splitting an empty string returns a single-element array containing an empty string – not an empty array. Use Groovy’s safe navigation operator ?. to handle null strings.
Example 11: Java Pattern.split() vs Groovy split()
What we’re doing: Comparing Java’s compiled Pattern.split() with Groovy’s string split() for performance and reusability.
Example 11: Pattern.split()
import java.util.regex.Pattern
def data = "apple::banana::cherry::date"
// Method 1: String.split() - compiles regex every call
def parts1 = data.split("::")
println "String.split: ${parts1 as List}"
// Method 2: Precompiled Pattern - reuse for multiple splits
def pattern = Pattern.compile("::")
def parts2 = pattern.split(data)
println "Pattern.split: ${parts2 as List}"
// Method 3: Groovy's bitwiseNegate for pattern
def groovyPattern = ~/::/
def parts3 = groovyPattern.split(data)
println "Groovy pattern: ${parts3 as List}"
// Pattern with limit
def parts4 = pattern.split(data, 2)
println "Pattern limit 2: ${parts4 as List}"
// Reusing pattern across multiple strings
def lines = ["one::two::three", "alpha::beta", "x::y::z::w"]
lines.each { line ->
println " ${pattern.split(line) as List}"
}
Output
String.split: [apple, banana, cherry, date] Pattern.split: [apple, banana, cherry, date] Groovy pattern: [apple, banana, cherry, date] Pattern limit 2: [apple, banana::cherry::date] [one, two, three] [alpha, beta] [x, y, z, w]
What happened here: When you call String.split(regex), Java compiles the regex into a Pattern internally every single time. If you’re splitting many strings with the same pattern, precompiling with Pattern.compile() is more efficient. Groovy’s ~/regex/ syntax is shorthand for Pattern.compile(). For one-off splits, String.split() is perfectly fine – the difference only matters in tight loops processing thousands of strings.
Example 12: Real-World Parsing Scenarios
What we’re doing: Practical real-world examples combining split with other Groovy features.
Example 12: Real-World Scenarios
// Parse a log line
def logLine = "2026-03-08 14:30:22 [ERROR] com.app.Service - Connection timeout"
def (date, time, level, source, _, message) = logLine.split(/\s+/, 6)
level = level.replaceAll(/[\[\]]/, '')
println "Date: ${date}, Level: ${level}, Message: ${message}"
// Parse a file path
def filePath = "/home/user/projects/groovy/src/Main.groovy"
def pathParts = filePath.split("/").findAll { it }
println "Directory: ${pathParts[0..-2].join('/')}"
println "Filename: ${pathParts[-1]}"
println "Extension: ${pathParts[-1].split(/\./)[-1]}"
// Parse environment variables
def envString = "JAVA_HOME=/usr/lib/jvm/java-17;GROOVY_HOME=/opt/groovy;PATH=/usr/bin"
def env = envString.split(";").collectEntries {
def (k, v) = it.split("=", 2)
[k, v]
}
println "JAVA_HOME: ${env.JAVA_HOME}"
println "All env keys: ${env.keySet()}"
// Split and aggregate
def scores = "85,92,78,95,88,91,76,83"
def scoreList = scores.split(",").collect { it.toInteger() }
println "Average: ${scoreList.sum() / scoreList.size()}"
println "Max: ${scoreList.max()}, Min: ${scoreList.min()}"
Output
Date: 2026-03-08, Level: ERROR, Message: Connection timeout Directory: home/user/projects/groovy/src Filename: Main.groovy Extension: groovy JAVA_HOME: /usr/lib/jvm/java-17 All env keys: [JAVA_HOME, GROOVY_HOME, PATH] Average: 86 Max: 95, Min: 76
What happened here: These are patterns you’ll use in production code. The log parser uses split(/\s+/, 6) with a limit to avoid splitting the message itself. The file path parser combines split with findAll to remove the empty first element from the leading slash. The scores example shows how split feeds naturally into Groovy’s aggregate methods like sum(), max(), and min().
split() vs tokenize() – When to Use Which
This is probably the most common question Groovy developers ask about string splitting. Both methods break strings apart, but they behave quite differently. We have a dedicated tokenize() guide, but here’s the head-to-head comparison:
| Feature | split() | tokenize() |
|---|---|---|
| Returns | String[] (Java array) | List<String> (Groovy list) |
| Delimiter | Regex pattern | Character(s) as literal |
| Empty elements | Keeps them (except trailing) | Always removes them |
| Multi-char delimiter | Treated as one pattern | Each char is a separate delimiter |
| Source | Java String + Groovy GDK | Groovy GDK only |
| Regex support | Yes | No |
split() vs tokenize()
def data = "one,,two,,,three"
// split keeps empty elements
def splitResult = data.split(",")
println "split: ${splitResult as List} (${splitResult.length} items)"
// tokenize removes empty elements
def tokenResult = data.tokenize(",")
println "tokenize: ${tokenResult} (${tokenResult.size()} items)"
// Multi-character delimiter difference
def path = "com.technoscripts.groovy"
// split treats ".t" as a regex pattern
println "split('.\\.t'): ${'com.technoscripts'.split(/\.t/) as List}"
// tokenize treats each char as a separate delimiter
println "tokenize('.t'): ${'com.technoscripts'.tokenize('.t')}"
// Return type matters
def parts = "a,b,c"
println "split type: ${parts.split(',').getClass().simpleName}"
println "tokenize type: ${parts.tokenize(',').getClass().simpleName}"
Output
split: [one, , two, , , three] (6 items)
tokenize: [one, two, three] (3 items)
split('.\\.t'): [com, echnoscripts]
tokenize('.t'): [com, echnoscrip, s]
split type: String[]
tokenize type: ArrayList
Quick rules: Use split() when you need regex patterns, want to preserve empty elements, or need a specific number of parts. Use tokenize() when you want a clean list with no empties and simple character-based splitting.
Edge Cases and Gotchas
Gotcha 1: Dot is a Regex Metacharacter
Regex Metacharacter Gotcha
def filename = "report.final.2026.csv"
// WRONG - dot matches ANY character in regex
def wrong = filename.split(".")
println "Wrong: ${wrong as List}" // Splits on every character!
// CORRECT - escape the dot
def correct1 = filename.split(/\./)
println "Correct (slashy): ${correct1 as List}"
def correct2 = filename.split("\\.")
println "Correct (escaped): ${correct2 as List}"
// Other characters that need escaping in regex:
// . * + ? ^ $ { } [ ] ( ) | \
def pipe = "a|b|c"
println "Pipe: ${pipe.split(/\|/) as List}"
Output
Wrong: [] Correct (slashy): [report, final, 2026, csv] Correct (escaped): [report, final, 2026, csv] Pipe: [a, b, c]
This trips up everyone at least once. The dot . in regex means “any character,” so split(".") splits on every character, producing an array of empty strings that get trimmed away. Always escape regex metacharacters with \ or use Pattern.quote() for literal strings.
Gotcha 2: Trailing Empty Elements Disappear
Trailing Empties Gotcha
import java.util.regex.Pattern
def row = "Alice,,30,,"
// Default - trailing empties removed
println "Default: ${row.split(',') as List} (${row.split(',').length})"
// Limit -1 - keep everything
println "Limit -1: ${row.split(',', -1) as List} (${row.split(',', -1).length})"
// Pattern.quote() for literal delimiters
def weirdDelim = "data[1]data[2]data[3]"
def parts = weirdDelim.split(Pattern.quote("["))
println "Quoted: ${parts as List}"
Output
Default: [Alice, , 30] (3) Limit -1: [Alice, , 30, , ] (5) Quoted: [data, 1]data, 2]data, 3]]
When processing fixed-width data or database exports, missing trailing fields can cause bugs if you’re counting on a specific number of columns. Always use split(delimiter, -1) when the number of fields matters. And use Pattern.quote() when your delimiter contains regex special characters and you want literal matching.
Performance Considerations
For most use cases, split() performance is a non-issue. But if you’re processing thousands of lines in a tight loop, here are things to know:
Performance Tips
import java.util.regex.Pattern
// Tip 1: Precompile patterns for repeated use
def pattern = Pattern.compile(",")
def lines = (1..5).collect { "a,b,c,d,e" }
// Slower - recompiles regex each time
lines.each { it.split(",") }
// Faster - reuses compiled pattern
lines.each { pattern.split(it) }
// Tip 2: For single-character delimiters, Java 8+
// internally optimizes split() - no regex compilation needed
// This is fast even without precompiling:
"a,b,c".split(",") // Java detects single char, skips regex
// Tip 3: Convert to List only when needed
def parts = "a,b,c".split(",")
// Access by index directly - no need for toList()
println parts[0] // Fast - direct array access
println parts.length // Fast - array length
// Only convert when you need List methods
def list = parts.toList()
println list.contains("b") // Now it's a List
Output
a 3 true
Since Java 8, the JVM optimizes single-character split() calls internally – it detects the pattern is a single literal character and uses a fast path that skips regex compilation entirely. For multi-character patterns or complex regex, precompiling with Pattern.compile() gives a measurable improvement when splitting thousands of strings.
Best Practices
DO:
- Use slashy strings
/pattern/for regex patterns to avoid double-escaping - Use
split(delimiter, -1)when you need to preserve trailing empty fields - Use
split(delimiter, 2)when you only want to split on the first occurrence - Escape regex metacharacters (
.,|,*, etc.) or usePattern.quote() - Precompile patterns with
Pattern.compile()or~/regex/for repeated splits - Chain
collect()andfindAll()after split for clean transformation pipelines
DON’T:
- Use
split(".")without escaping – it matches every character - Assume
split()returns a List – it returnsString[] - Forget that trailing empty elements are removed by default
- Use
split()for simple CSV with quoted fields – use a proper CSV library instead - Call
split()on a potentially null string without the?.safe navigation operator
Conclusion
We covered the key techniques for Groovy split string operations – from basic comma splitting to regex-powered parsing, the limit parameter, CSV handling, multiline splitting, and all the edge cases that can bite you in production.
The split() method is powerful precisely because it takes regex patterns. That power comes with responsibility – you need to remember to escape metacharacters, understand trailing element behavior, and know when tokenize() is the simpler choice. But once you internalize these patterns, splitting strings in Groovy becomes second nature.
For more on string operations, check out our complete Groovy String tutorial and the companion tokenize() guide.
Summary
split()takes a regex pattern and returnsString[]– not a List- Use
split(regex, -1)to keep trailing empty elements - Use
split(regex, 2)to split only on the first match - Always escape regex metacharacters like
.and| - Prefer
tokenize()when you want a List and don’t need regex or empty elements
If you also work with build tools, CI/CD pipelines, or cloud CLIs, check out Command Playground to practice 105+ CLI tools directly in your browser — no install needed.
Up next: Groovy GString – String Interpolation Made Easy
Frequently Asked Questions
What does split() return in Groovy – an array or a list?
The split() method returns a String[] (Java array), not a Groovy List. If you need a List, convert it with toList() or use the as List cast. Alternatively, use tokenize() which returns a List directly.
How do I split a Groovy string by dot (period)?
You must escape the dot because it’s a regex metacharacter. Use split(/\./) with a slashy string, or split("\\.") with a regular string, or Pattern.quote("."). Without escaping, split(".") matches any character and produces unexpected results.
What is the difference between split() and tokenize() in Groovy?
split() uses regex patterns, returns a String[], and preserves empty elements. tokenize() uses literal characters as delimiters, returns a List, and automatically removes empty elements. Use split() for regex-based splitting and tokenize() for simple character-based splitting.
How do I keep trailing empty elements when using split()?
Pass -1 as the second argument: split(",", -1). By default, split() removes trailing empty strings from the result array. The -1 limit tells it to apply the pattern as many times as possible and keep all elements including trailing empties.
Can I split a string on multiple delimiters in Groovy?
Yes, use a regex character class. For example, split(/[,;|]/) splits on comma, semicolon, or pipe. You can also use alternation: split(/,|;|\|/). Remember that split() treats its argument as a regex pattern, so you have full regex power for matching delimiters.
Related Posts
Previous in Series: Groovy Tokenize – Split Strings Without the Empties
Next in Series: Groovy GString – String Interpolation Made Easy
Related Topics You Might Like:
- Groovy String Tutorial – The Complete Guide
- Groovy Substring – Extract Parts of a String
- Groovy Regular Expressions – Pattern Matching
This post is part of the Groovy & Grails Cookbook series on TechnoScripts.com

No comment