Apache Groovy’s Ternary operator: Simplifying conditional expressions
In this article, you’ll explore how those concepts apply to the ternary operator, inherited from the C-language with Java. (If you haven’t installed Groovy yet, please read the intro to this series.)
Let’s start with a Java-esque Groovy script that uses the ternary operator to convert the string version of a parameter to an integer where possible. It also supplies the default value of 0:
1 String strParam = "42"
2 int intParam = strParam != null && strParam.isInteger() ? Integer.parseInt(strParam) : 0
3 println "strParam = '$strParam' intParam = $intParam"
4 strParam = "xyz"
5 intParam = strParam != null && strParam.isInteger() ? Integer.parseInt(strParam) : 0
6 println "strParam = '$strParam' intParam = $intParam"
7 strParam = null
8 intParam = strParam != null && strParam.isInteger() ? Integer.parseInt(strParam) : 0
9 println "strParam = '$strParam' intParam = $intParam"
The same condition is tested on lines two, five and eight. If the string parameter has a value and if that value can be converted to an integer, then the integer parameter receives the converted value — otherwise, the integer parameter is set to 0.
Running this yields:
$ groovy Groovy07a.groovy
strParam = ‘42' intParam = 42
strParam = ‘xyz' intParam = 0
strParam = ‘null' intParam = 0
$
This gives the expected results.
In the previous article, you learned that Groovy’s version of truth means you don’t need to test for not null. Instead, you can just do the following:
1 String strParam = "42"
2 int intParam = strParam && strParam.isInteger() ? Integer.parseInt(strParam) : 0
3 println "strParam = '$strParam' intParam = $intParam"
4 strParam = "xyz"
5 intParam = strParam && strParam.isInteger() ? Integer.parseInt(strParam) : 0
6 println "strParam = '$strParam' intParam = $intParam"
7 strParam = null
8 intParam = strParam && strParam.isInteger() ? Integer.parseInt(strParam) : 0
9 println "strParam = '$strParam' intParam = $intParam"
Running this, you get:
$ groovy Groovy07b.groovy
strParam = ‘42' intParam = 42
strParam = ‘xyz' intParam = 0
strParam = ‘null' intParam = 0
$
That makes the code a little more compact and easy to read. In the next article, you learn about safe navigation that reduces this complexity further. But for now, look at the Elvis operator, which is a version of the ternary operator created to complement the Groovy truth and simplify statements of the form:
expression1 ? expression1 : expression2
The Elvis operator is a great example of one of Groovy’s central themes — Don’t Repeat Yourself, or DRY.
Let’s think about a similar situation where you have a potentially null or 0 argument to a method or script. For this, you want to have a sensible default value in that case:
1 def copies = null
2 copies = copies ?: 1
3 println "copies $copies"
4 copies = 0
5 copies = copies ?: 1
6 println "copies $copies"
7 copies = 5
8 copies = copies ?: 1
9 println "copies $copies"
When you run this, you see:
$ groovy Groovy07c.groovy
copies 1
copies 1
copies 5
$
Groovy 3 further contracted the Elvis operator to the even more DRY Elvis assignment operator:
1 def copies = null
2 copies ?= 1
3 println "copies $copies"
4 copies = 0
5 copies ?= 1
6 println "copies $copies"
7 copies = 5
8 copies ?= 1
9 println "copies $copies"
Look what happens when you run this:
$ groovy Groovy07d.groovy
copies 1
copies 1
copies 5
$
Conclusion
The Groovy truth can make expressions using the ternary operator more compact, more readable, and therefore more maintainable. The Elvis operator and Elvis assignment statement offer further possibilities in writing more compact and readable code.
In my experience writing Groovy, I find I use the ternary operator much more than in Java because of the DRY principle. Ternary expressions in Java can reach a degree of complexity and wordiness that needs extremely careful and thoughtful reading. I often prefer to use if – then – else in Java. This isn’t so in Groovy!
Finally, compact ternary expressions have a real home in Groovy closures that need to return different values depending on circumstances, such as when using .collect() to prepare a list of values.
Photo by Mike Enerio on Unsplash
