Groovy Guide — Control Flow: Conditionals and Loops
In this tutorial, you will learn about Groovy Guide. We cover key concepts, practical examples, and best practices to help you master this topic.
Groovy control flow enhances Java's syntax with truthy/falsy semantics, switch on any type, elvis operator, and idiomatic iteration using each/find/inject patterns.
What You'll Learn
- Truthy and falsy in Groovy
- Elvis and safe navigation operators
- Switch with any type
- Each, find, and collect loops
- Exception Handling
Why It Matters
Groovy's control flow reduces boilerplate and makes conditions expressive. Durga Antivirus Pro uses these patterns for rule evaluation.
Real-World Use
Configuration processing, data validation, and workflow Orchestration benefit from Groovy's control flow.
flowchart LR
A["Control Flow"] --> B["Truthy/Falsy"]
B --> C["Operators"]
C --> D["Switch"]
D --> E["Loops"]
A:::current --> B
style A fill:#2563eb,stroke:#2563eb,color:#fff
style B fill:#dbeafe,stroke:#2563eb,color:#1e40af
style C fill:#dbeafe,stroke:#2563eb,color:#1e40af
style D fill:#dbeafe,stroke:#2563eb,color:#1e40af
style E fill:#f1f5f9,stroke:#94a3b8,color:#64748b
Truthy and Falsy
// Falsy: false, null, 0, "", [], [:]
// Everything else is truthy
if (list) { // false if empty list
println "list has elements"
}
if (str) { // false if null or empty
println "string is not empty"
}
if (map) { // false if empty map
println "map has entries"
}
Elvis Operator
def name = null
def display = name ?: "Default Name"
// "Default Name"
// With nested access
def user = [profile: [name: "Alice"]]
def username = user?.profile?.name ?: "Anonymous"
// Ternary
def status = age >= 18 ? "Adult" : "Minor"
Safe Navigation
class Address { String city }
class Person { Address address }
def person = null
person?.address?.city // null (no NPE)
def person2 = new Person()
person2?.address?.city // null (no NPE)
person2?.address = new Address(city: "Portland")
person2?.address?.city // "Portland"
Switch
def evaluate(value) {
switch(value) {
case 0:
return "Zero"
case 1..10:
return "Small"
case { it > 100 }:
return "Large"
case String:
return "String type"
case ~/^\d+$/:
return "Numeric string"
case [1, 2, 3]:
return "In list"
default:
return "Other"
}
}
Loops
// Each iteration
[1, 2, 3].each { println it }
[1, 2, 3].eachWithIndex { val, idx ->
println "$idx: $val"
}
// Find
def first = [1, 2, 3, 4].find { it > 2 } // 3
def all = [1, 2, 3, 4].findAll { it > 2 } // [3, 4]
// Any/Every
def hasEven = [1, 2, 3].any { it % 2 == 0 } // true
def allEven = [2, 4, 6].every { it % 2 == 0 } // true
Classic Loops
// For loop
for (i in 0..5) {
println i
}
// For with list
for (item in [1, 2, 3]) {
println item
}
// While
def i = 0
while (i < 5) {
println i++
}
// Times
5.times { println it } // Prints 0-4
Exception Handling
try {
riskyOperation()
} catch (IOException e) {
println "IO error: $e.message"
} catch (Exception e) {
println "Error: $e.message"
} finally {
cleanup()
}
// Try with resources
try (def reader = new FileReader("file.txt")) {
println reader.text
}
Common Mistakes
1. Assuming Java truthy rules
Groovy considers empty collections falsy. Java considers empty collections truthy.
2. Elvis operator with boolean values
active ?: true returns true even if active is false. Use ternary for boolean checks.
3. Switch fall-through
Groovy switch doesn't fall through without explicit code. Each case needs its own logic.
4. Forgetting safe navigation
Use ?. for chains that may have null values. Prevents NPE.
5. Using == for identity
Groovy's == calls equals(). Use is() for reference identity.
Practice Questions
1. What values are falsy in Groovy? false, null, 0, empty strings, empty collections (lists, maps, etc.).
2. What does the Elvis operator (?:) do? Returns the left operand if truthy, otherwise the right operand. Works as a short-circuit default.
3. How does Groovy switch differ from Java? Groovy switch handles any object type, ranges, closures, regex patterns, and lists as cases.
Challenge: Write a grade calculator using Groovy switch with range cases.
FAQ
{{< faq question="Is Groovy's == different from Java's?" >} Yes. Groovy's == maps to .equals(). Use .is() for reference identity (Java's ==). {{< /faq >}}
{{< faq question="Can I use Java-style for loops?" >} Yes. Standard Java for, while, and do-while loops all work in Groovy. {{< /faq >}}
{{< faq question="What is the spread-dot operator?" >}
*., the spread-dot operator, calls a method on each element: list*.toUpperCase().
{{< /faq >}}
{{< faq question="Can I use Groovy's truthy rules in Java interop?" >} No. When calling Java methods, use standard Java truthiness. Groovy truthiness only applies in Groovy code. {{< /faq >}}
{{< faq question="What is the spaceship operator?" >} <=> is the comparison operator. Returns -1, 0, or 1 for less than, equal, greater than. {{< /faq >}}
Mini Project
Build a validation function with Groovy control flow:
def validateUser(user) {
def errors = []
if (!user.name) {
errors << "Name is required"
}
if (!user.email || !(user.email =~ /.+@.+\..+/)) {
errors << "Valid email is required"
}
if (user.age !in 0..150) {
errors << "Age must be 0-150"
}
return errors ? new ValidationResult(false, errors)
: new ValidationResult(true, ["User is valid"])
}
@groovy.transform.Canonical
class ValidationResult {
boolean valid
List<String> messages
}
def user = [name: "Alice", email: "invalid", age: 200]
println validateUser(user)
What's Next
Now that you understand control flow, explore GPath for navigating object graphs.
| Topic | Description | Link |
|---|---|---|
| Groovy GPath | Object graph navigation | {{< ref "08-gpath" >}} |
| Groovy Builders | Builder pattern | {{< ref "09-builders" >}} |
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro