Groovy string reverse method is demonstrated with 10 tested examples. Reverse strings, check palindromes, and more. Complete guide for Groovy 5.x.
“Sometimes the best way to understand a string is to look at it backwards.”
Alan Perlis, Epigrams on Programming
Last Updated: March 2026 | Tested on: Groovy 5.x, Java 17+ | Difficulty: Beginner | Reading Time: 12 minutes
The groovy string reverse method is deceptively simple – call reverse() on any string and you get the characters flipped. But it pops up in more places than you’d expect: palindrome checks, reversing user input for display, building mirrored text effects, parsing data that comes in backwards order. It’s a surprisingly common operation.
In Java, reversing a string means creating a StringBuilder, calling .reverse(), and then converting back to a String. It works, but it’s three steps for something that should be one. Groovy fixes this by adding a reverse() method directly to the String class through the GDK (Groovy Development Kit).
In this post, we’ll explore groovy string reverse with 10 tested examples — from basic reversals to palindrome checking, reversing words in a sentence, working with Unicode, and comparing approaches for performance. If you’re new to Groovy strings in general, start with our Groovy String Tutorial first. And if you’ve been following along with take(), you’ll see how reverse() combines nicely with it.
Table of Contents
What is Groovy String reverse()?
The reverse() method is a GDK extension added to java.lang.String. It returns a new string with the characters in the opposite order. The original string stays unchanged because strings in Groovy (and Java) are immutable.
According to the official Groovy GDK String documentation, reverse() creates a new string that is the reverse of the original. It’s part of Groovy’s philosophy of making common operations dead simple.
Key Points:
reverse()is a GDK method — not part of standard Java’s String class- It returns a new string — the original is never modified
- Works on any
StringorGStringvalue - Also available on lists and other collections in Groovy
- Handles empty strings and single-character strings gracefully
Why Use reverse() in Groovy?
You might wonder — how often do I actually need to reverse a string? More often than you’d think. Here are real scenarios where reverse() comes in handy:
- Palindrome detection: Check if a word or phrase reads the same forwards and backwards
- Data validation: Verify symmetrical codes, account numbers, or serial formats
- String algorithms: Many interview questions and algorithms use string reversal as a building block
- Log parsing: Extract information from the end of strings by reversing, taking, and reversing back
- Text effects: Build mirrored text, reversed displays, or creative formatting
- File extension extraction: Reverse, find the first dot, reverse again — works for nested extensions too
The biggest advantage? In Groovy, it’s a one-liner. No StringBuilder, no character arrays, no manual loops. Just "hello".reverse() and you’re done.
Syntax and Basic Usage
Basic Syntax
reverse() Syntax
// Syntax String result = originalString.reverse() // Basic usage def reversed = "Groovy".reverse() println reversed // yvoorG
The method takes no parameters and returns a new String. That’s it. No arguments, no configuration, no surprises. The returned string contains all the same characters as the original, just in the opposite order.
Method Signature
Method Signature
// From the GDK (DefaultGroovyMethods) public static String reverse(CharSequence self)
Notice that the method actually works on any CharSequence, not just String. This means it works on GString, StringBuilder, and any other CharSequence implementations.
10 Practical reverse() Examples
Example 1: Basic String Reversal
What we’re doing: Reversing simple strings to see how reverse() works at its most basic level.
Example 1: Basic Reversal
def word = "Groovy"
println word.reverse()
def number = "12345"
println number.reverse()
def sentence = "Hello World"
println sentence.reverse()
// Original is unchanged
println "Original: ${word}"
Output
yvoorG 54321 dlroW olleH Original: Groovy
What happened here: Each call to reverse() returns a new string with all characters flipped. Spaces, uppercase letters, digits — everything gets reversed in order. The original string remains untouched because strings are immutable in Groovy.
Example 2: Reverse with Collections
What we’re doing: Using reverse() on lists and combining it with string operations.
Example 2: Reverse with Collections
// Reverse a list
def fruits = ['apple', 'banana', 'cherry']
println fruits.reverse()
// Reverse each string in a list
def words = ['cat', 'dog', 'bird']
println words.collect { it.reverse() }
// Reverse a list and join
def letters = ['a', 'b', 'c', 'd', 'e']
println letters.reverse().join('')
// Convert string to list, reverse, join back
def text = "Groovy"
println text.toList().reverse().join('')
Output
[cherry, banana, apple] [tac, god, drib] edcba yvoorG
What happened here: The reverse() method works on both strings and lists in Groovy. When applied to a list, it reverses the element order. We used collect() to reverse each individual string inside a list, and toList() to convert a string to a character list before reversing.
Example 3: Palindrome Checker
What we’re doing: Building a palindrome checker using reverse().
Example 3: Palindrome Checker
// Simple palindrome check
def isPalindrome = { str ->
def clean = str.toLowerCase().replaceAll(/[^a-z0-9]/, '')
clean == clean.reverse()
}
println "madam: ${isPalindrome('madam')}"
println "hello: ${isPalindrome('hello')}"
println "racecar: ${isPalindrome('racecar')}"
println "A man a plan a canal Panama: ${isPalindrome('A man a plan a canal Panama')}"
println "Was it a car or a cat I saw: ${isPalindrome('Was it a car or a cat I saw')}"
println "12321: ${isPalindrome('12321')}"
Output
madam: true hello: false racecar: true A man a plan a canal Panama: true Was it a car or a cat I saw: true 12321: true
What happened here: We strip out non-alphanumeric characters and convert to lowercase, then compare the cleaned string with its reverse. If they’re equal, it’s a palindrome. This is the classic use case for reverse() and it’s a two-liner in Groovy. In Java, you’d need at least four or five lines to do the same thing.
Example 4: Reverse Words in a Sentence
What we’re doing: Reversing the order of words in a sentence without reversing the characters within each word.
Example 4: Reverse Words in Sentence
def sentence = "Groovy is a powerful language"
// Reverse word order (not characters)
def reversedWords = sentence.split(' ').toList().reverse().join(' ')
println "Word order reversed: ${reversedWords}"
// Reverse each word but keep order
def reversedEachWord = sentence.split(' ').collect { it.reverse() }.join(' ')
println "Each word reversed: ${reversedEachWord}"
// Reverse both word order AND each word
def fullyReversed = sentence.split(' ').collect { it.reverse() }.reverse().join(' ')
println "Fully reversed: ${fullyReversed}"
// Compare with simple string reverse
println "String reverse: ${sentence.reverse()}"
Output
Word order reversed: language powerful a is Groovy Each word reversed: yvoorG si a lufrewop egaugnal Fully reversed: egaugnal lufrewop a si yvoorG String reverse: egaugnal lufrewop a si yvoorG
What happened here: There’s a difference between reversing the word order and reversing the entire string character by character. We split the sentence into words, then used reverse() at different levels. Notice that reversing both the word order and each individual word gives the same result as a plain reverse() on the whole string — which makes sense mathematically.
Example 5: Reverse with Unicode and Special Characters
What we’re doing: Testing how reverse() handles Unicode characters, emojis, and special symbols.
Example 5: Unicode and Special Characters
// Accented characters
def french = "caf\u00E9"
println "Original: ${french} -> Reversed: ${french.reverse()}"
// Special symbols
def symbols = "a@b#c"
println "Symbols: ${symbols.reverse()}"
// Mixed case and numbers
def mixed = "Abc123Xyz"
println "Mixed: ${mixed.reverse()}"
// Newlines and tabs
def multiline = "line1\nline2\nline3"
println "Multiline reversed:"
println multiline.reverse()
// Empty and whitespace
println "Empty: '${'' .reverse()}'"
println "Spaces: '${' '.reverse()}'"
Output
Original: café -> Reversed: éfac Symbols: c#b@a Mixed: zyX321cbA Multiline reversed: 3enil 2enil 1enil Empty: '' Spaces: ' '
What happened here: Groovy’s reverse() handles basic Unicode characters (like accented letters) correctly because they fit within a single Java char. Special symbols, digits, and whitespace all reverse as expected. Even newlines get reversed — the entire string is treated as a flat sequence of characters. Empty strings return empty strings, and spaces stay as spaces.
Example 6: reverse() vs StringBuilder.reverse()
What we’re doing: Comparing Groovy’s reverse() with Java’s StringBuilder.reverse() approach.
Example 6: Groovy vs Java Approach
def text = "Hello Groovy"
// Groovy way - one method call
def groovyReversed = text.reverse()
println "Groovy way: ${groovyReversed}"
// Java way - StringBuilder
def javaReversed = new StringBuilder(text).reverse().toString()
println "Java way: ${javaReversed}"
// Are they equal?
println "Same result: ${groovyReversed == javaReversed}"
// Java way is 3 steps:
// 1. Create StringBuilder
// 2. Call reverse()
// 3. Convert back to String
// Groovy does it in 1 step
// Manual loop approach (never do this)
def manual = ''
for (int i = text.length() - 1; i >= 0; i--) {
manual += text[i]
}
println "Manual way: ${manual}"
println "All equal: ${groovyReversed == javaReversed && javaReversed == manual}"
Output
Groovy way: yvoorG olleH Java way: yvoorG olleH Same result: true Manual way: yvoorG olleH All equal: true
What happened here: All three approaches produce the same result, but Groovy’s reverse() is by far the cleanest. The Java StringBuilder approach requires creating an intermediate object, calling reverse, then converting back. The manual loop is worst — it creates a new string on every iteration. Under the hood, Groovy’s reverse() uses an efficient character array approach, so you get both readability and performance.
Example 7: Reverse with take() and drop()
What we’re doing: Combining reverse() with take() and drop() for creative string manipulation.
Example 7: Combining reverse with take/drop
def text = "Groovy Programming"
// Get last 5 characters using reverse + take + reverse
def lastFive = text.reverse().take(5).reverse()
println "Last 5 chars: ${lastFive}"
// Get everything except last 3 characters
def dropLast3 = text.reverse().drop(3).reverse()
println "Drop last 3: ${dropLast3}"
// Extract the last word
def lastWord = text.reverse().takeWhile { it != ' ' }.reverse()
println "Last word: ${lastWord}"
// Reverse just the first half
def half = text.length().intdiv(2)
def firstHalfReversed = text.take(half).reverse() + text.drop(half)
println "First half reversed: ${firstHalfReversed}"
// Swap first and last characters
def swapped = text[-1] + text.drop(1).reverse().drop(1).reverse() + text[0]
println "Swapped first/last: ${swapped}"
Output
Last 5 chars: mming Drop last 3: Groovy Programm Last word: Programming First half reversed: rP yvoorGogramming Swapped first/last: groovy ProgramminG
What happened here: This is where reverse() really shines in combination with other GDK methods. Need the last N characters? Reverse, take N, reverse back. Need to drop from the end? Reverse, drop, reverse back. The takeWhile trick extracts the last word by reversing and taking characters until a space is found. These patterns are incredibly useful in real-world string processing.
Example 8: Reversing Lists of Strings
What we’re doing: Using reverse() on various collection types.
Example 8: Reversing Lists
// Reverse a list of strings
def stack = ['first', 'second', 'third', 'fourth']
println "Original: ${stack}"
println "Reversed: ${stack.reverse()}"
// Reverse is non-mutating for lists too
println "Still original: ${stack}"
// Sort descending using reverse
def numbers = [3, 1, 4, 1, 5, 9, 2, 6]
println "Descending: ${numbers.sort().reverse()}"
// Reverse a range
def range = (1..10).toList()
println "Range reversed: ${range.reverse()}"
// Reverse and re-join CSV data
def csv = "Alice,Bob,Charlie,Diana"
def reversedCsv = csv.split(',').toList().reverse().join(',')
println "CSV reversed: ${reversedCsv}"
// Use reverse to get last N elements from a list
def lastTwo = stack.reverse().take(2)
println "Last 2 elements: ${lastTwo}"
Output
Original: [first, second, third, fourth] Reversed: [fourth, third, second, first] Still original: [first, second, third, fourth] Descending: [9, 6, 5, 4, 3, 2, 1, 1] Range reversed: [10, 9, 8, 7, 6, 5, 4, 3, 2, 1] CSV reversed: Diana,Charlie,Bob,Alice Last 2 elements: [fourth, third]
What happened here: Groovy’s reverse() on lists is non-mutating — it returns a new list, just like with strings. We used it for sorting in descending order, reversing CSV data, and grabbing the last N elements from a list. The pattern list.reverse().take(n) is a handy way to get the last N items.
Example 9: Performance Comparison
What we’re doing: Benchmarking different string reversal approaches to see which is fastest.
Example 9: Performance Benchmark
def text = "a" * 10000 // 10,000 character string
def iterations = 1000
// Groovy reverse()
def start1 = System.nanoTime()
iterations.times { text.reverse() }
def time1 = (System.nanoTime() - start1) / 1_000_000
println "Groovy reverse(): ${time1} ms"
// StringBuilder reverse
def start2 = System.nanoTime()
iterations.times { new StringBuilder(text).reverse().toString() }
def time2 = (System.nanoTime() - start2) / 1_000_000
println "StringBuilder reverse(): ${time2} ms"
// char array manual
def start3 = System.nanoTime()
iterations.times {
def chars = text.toCharArray()
int left = 0, right = chars.length - 1
while (left < right) {
char temp = chars[left]
chars[left] = chars[right]
chars[right] = temp
left++
right--
}
new String(chars)
}
def time3 = (System.nanoTime() - start3) / 1_000_000
println "Manual char array: ${time3} ms"
println "\nAll produce same result: ${text.reverse() == new StringBuilder(text).reverse().toString()}"
Output
Groovy reverse(): 85 ms StringBuilder reverse(): 92 ms Manual char array: 78 ms All produce same result: true
What happened here: All three approaches perform similarly because string reversal is an O(n) operation regardless of the implementation. The manual char array approach is marginally faster because it avoids object creation overhead, but the difference is negligible. Groovy’s reverse() is the clear winner when you factor in readability. For 99% of real-world use cases, performance is not a concern here — use reverse() and move on.
Note: Actual timings will vary based on JVM warmup, garbage collection, and hardware. The relative difference between approaches is what matters, and it’s minimal.
Example 10: Real-World Use Cases
What we’re doing: Applying reverse() to practical, real-world scenarios you might encounter in production code.
Example 10: Real-World Uses
// 1. Extract file extension (handles multiple dots)
def filename = "archive.backup.tar.gz"
def extension = filename.reverse().takeWhile { it != '.' }.reverse()
println "Extension: ${extension}"
// 2. Mask a credit card number (show last 4)
def card = "4532015112830366"
def masked = ("*" * (card.length() - 4)) + card.reverse().take(4).reverse()
println "Masked card: ${masked}"
// 3. Reverse DNS lookup format
def ip = "192.168.1.100"
def reverseDns = ip.split(/\./).toList().reverse().join('.')
println "Reverse DNS: ${reverseDns}"
// 4. Check if a string is a rotated palindrome
def isRotatedPalindrome = { str ->
def clean = str.toLowerCase().replaceAll(/[^a-z]/, '')
def doubled = clean + clean
(0..<clean.length()).any { i ->
def rotated = doubled.substring(i, i + clean.length())
rotated == rotated.reverse()
}
}
println "damma rotated palindrome: ${isRotatedPalindrome('damma')}"
// 5. Build a mirror string
def half = "ABCDE"
def mirror = half + half.reverse()
println "Mirror: ${mirror}"
// 6. Reverse path components
def path = "/home/user/documents/file.txt"
def reversedPath = path.split('/').toList().reverse().findAll { it }.join('/')
println "Reversed path: ${reversedPath}"
Output
Extension: gz Masked card: ************0366 Reverse DNS: 100.1.168.192 damma rotated palindrome: true Mirror: ABCDEEDCBA Reversed path: file.txt/documents/user/home
What happened here: These are patterns you’ll actually use. The file extension trick reverses the string, takes characters until a dot, then reverses back. Credit card masking uses reverse to grab the last four digits. Reverse DNS lookup is a common network operation. And the mirror string pattern shows up in UI and text effects. Each one is just a couple of lines thanks to reverse() combined with other Groovy methods.
Edge Cases and Best Practices
Edge Cases to Watch For
Edge Cases
// Empty string
println "Empty: '${''.reverse()}'"
// Single character
println "Single: '${'X'.reverse()}'"
// All same characters
println "Same chars: '${'aaaa'.reverse()}'"
// Only whitespace
println "Whitespace: '${' \t '.reverse()}'"
// null safety - reverse() on null throws NPE
try {
String nullStr = null
nullStr.reverse()
} catch (NullPointerException e) {
println "null throws: ${e.class.simpleName}"
}
// Safe navigation operator
String nullStr = null
println "Safe null: '${nullStr?.reverse()}'"
// Double reverse returns original
def original = "TechnoScripts"
println "Double reverse: ${original.reverse().reverse() == original}"
Output
Empty: '' Single: 'X' Same chars: 'aaaa' Whitespace: ' ' null throws: NullPointerException Safe null: 'null' Double reverse: true
Best Practices Summary
DO:
- Use
reverse()directly — it’s the cleanest and most readable approach - Use the safe navigation operator
?.when the string might be null - Combine
reverse()withtake()anddrop()for extracting from the end of strings - Remember that
reverse()is non-mutating — assign the result to a variable
DON’T:
- Write manual reversal loops —
reverse()is optimized and tested - Use
StringBuilder.reverse()in Groovy — the GDK method is simpler - Forget that reversing a string with surrogate pairs (some emojis, certain CJK characters) can produce invalid results
- Call
reverse()on null without the safe navigation operator
Performance Considerations
Groovy’s reverse() is an O(n) operation — it creates a new character array, fills it in reverse order, and wraps it in a new String. For most applications, this is plenty fast. Here’s what to keep in mind:
- Time complexity: O(n) where n is the string length — every character is visited once
- Space complexity: O(n) because a new string is created (strings are immutable)
- Repeated reversals: If you need to reverse the same string multiple times, cache the result
- Very large strings: For strings over 10MB, consider streaming or chunked processing instead
- In loops: Reversing inside a tight loop is fine — the operation itself is fast. The bottleneck is usually elsewhere
Performance Tip: Cache Reversed Strings
// If you reverse the same string repeatedly, cache it
def original = "Some long string that doesn't change"
def reversed = original.reverse() // compute once
// Use 'reversed' variable instead of calling reverse() each time
10.times {
println reversed // no re-computation
}
Output
Some long string that doesn't change egnahc t'nseod taht gnirts gnol emoS egnahc t'nseod taht gnirts gnol emoS egnahc t'nseod taht gnirts gnol emoS egnahc t'nseod taht gnirts gnol emoS egnahc t'nseod taht gnirts gnol emoS egnahc t'nseod taht gnirts gnol emoS egnahc t'nseod taht gnirts gnol emoS egnahc t'nseod taht gnirts gnol emoS egnahc t'nseod taht gnirts gnol emoS egnahc t'nseod taht gnirts gnol emoS
Bottom line: don’t overthink performance with reverse(). It’s fast enough for nearly every use case. Only optimize if profiling tells you string reversal is actually your bottleneck (spoiler: it almost never is).
Common Pitfalls
Pitfall 1: Expecting In-Place Mutation
Pitfall 1: Not Assigning the Result
def text = "Hello" // WRONG - reverse() returns a new string, doesn't modify original text.reverse() println text // Still "Hello"! // CORRECT - assign the result def reversed = text.reverse() println reversed // "olleH" // Or reassign text = text.reverse() println text // "olleH"
Output
Hello olleH olleH
This is the most common mistake. Because strings are immutable, reverse() creates and returns a new string. If you don’t capture the return value, the reversed string is thrown away immediately.
Pitfall 2: Surrogate Pairs and Emojis
Pitfall 2: Surrogate Pairs
// Basic BMP characters work fine
def basic = "ABC"
println basic.reverse() // CBA
// But characters outside the BMP (emojis, some CJK)
// use surrogate pairs (two Java chars per character)
// Reversing can break them because the pair gets split
// Safe approach for surrogate-pair-aware reversal:
def safeReverse = { str ->
new StringBuilder(str).reverse().toString()
}
println "Safe reverse: ${safeReverse('ABC')}"
Output
CBA Safe reverse: CBA
For most strings with standard characters, reverse() works perfectly. But if your strings contain characters outside the Basic Multilingual Plane (certain emojis, rare CJK characters), Java’s StringBuilder.reverse() handles surrogate pairs more carefully. In practice, this only matters if you’re processing user-generated content with emojis.
Pitfall 3: Reversing GStrings
Pitfall 3: GString Reversal
def name = "Groovy"
// GString gets evaluated first, then reversed
def gstring = "Hello ${name}"
println gstring.reverse() // yvoorG olleH (correct)
// The interpolation happens BEFORE reverse
// reverse() sees "Hello Groovy", not "Hello ${name}"
println gstring.class.name // org.codehaus.groovy.runtime.GStringImpl
println gstring.reverse().class.name // java.lang.String
Output
yvoorG olleH org.codehaus.groovy.runtime.GStringImpl java.lang.String
When you call reverse() on a GString, Groovy first evaluates the interpolations to produce a plain string, then reverses it. The result is always a java.lang.String, not a GString. This is usually exactly what you want, but it’s good to understand the sequence of operations.
Conclusion
The Groovy string reverse method is a small but mighty tool in your Groovy toolkit. What takes three steps in Java — create a StringBuilder, call reverse, convert back — is a single method call in Groovy. And as we’ve seen across these 10 examples, it’s not just about flipping characters. Palindrome checking, extracting from the end of strings, reversing word order, working with collections, and building real-world utilities like credit card masking and reverse DNS — reverse() is the building block for all of them.
The bottom line is simple: use reverse() and don’t overthink it. It’s fast, it’s readable, and it handles edge cases like empty strings and single characters gracefully. Just remember it’s non-mutating — always assign the result.
For more string manipulation techniques, check out our posts on take() and drop(), which combine beautifully with reverse() for powerful string processing.
Summary
reverse()is a GDK method that returns a new string with characters in opposite order- It works on both strings and lists — same method name, same behavior
- It’s non-mutating — always assign the result to a variable
- Combine with
take()anddrop()to extract from the end of strings - Performance is O(n) and fast enough for virtually all use cases
- Watch out for surrogate pairs (emojis) — use
StringBuilder.reverse()if you need surrogate-aware reversal
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 String drop() – Skip First N Characters
Frequently Asked Questions
How do I reverse a string in Groovy?
Call the reverse() method directly on any string: ‘hello’.reverse() returns ‘olleh’. This is a GDK method added to java.lang.String, so it works on any string in Groovy without imports. The method returns a new string and does not modify the original.
Does Groovy reverse() modify the original string?
No. Strings in Groovy (and Java) are immutable. The reverse() method returns a new string with the characters in reverse order. The original string remains unchanged. You must assign the result to a variable: def reversed = myString.reverse().
Can I use reverse() on a list in Groovy?
Yes. Groovy’s reverse() works on both strings and lists. For lists, it returns a new list with elements in the opposite order. For example, [1, 2, 3].reverse() returns [3, 2, 1]. Like with strings, the original list is not modified.
How do I check if a string is a palindrome in Groovy?
Clean the string (remove non-alphanumeric characters, convert to lowercase), then compare it with its reverse. Example: def clean = str.toLowerCase().replaceAll(/[^a-z0-9]/, ''); return clean == clean.reverse(). This handles phrases like ‘A man a plan a canal Panama’.
Is Groovy reverse() safe with Unicode and emojis?
Groovy’s reverse() works correctly with standard Unicode characters (BMP range). However, characters outside the Basic Multilingual Plane (certain emojis, rare scripts) use surrogate pairs in Java, and reversing them can break the pairs. For surrogate-aware reversal, use new StringBuilder(str).reverse().toString() instead.
Related Posts
Previous in Series: Groovy String take() – Get First N Characters
Next in Series: Groovy String drop() – Skip First N Characters
Related Topics You Might Like:
- Groovy String Tutorial – The Complete Guide
- Groovy Substring – Extract Parts of a String
- Groovy Compare Strings – equals, compareTo, and More
This post is part of the Groovy & Grails Cookbook series on TechnoScripts.com

No comment