I am building a string in this way:
def presentationType = "${feedDisplayType}, ${moduleType}, ${cellType}"
What happens is that sometimes the variables has null values, and the resulting string is showing this null values, I have to avoid show null values.
I want to know if there is some way to remove this possible null values in the string or avoid add this when they will be presented.
I know that it is possible and more easy to do with arrays, but I want to do it with strings in a more direct way.
Thanks for any help in advance.
There are 3 options:
def presentationType = "${feedDisplayType != null && !feedDisplayType.isEmpty() ? feedDisplayType + ', ' : ''}${moduleType != null && !moduleType.isEmpty() ? moduleType + ', ' : ''}${cellType != null && !cellType.isEmpty() ? cellType : ''}".toString()
StringBuilder
def sb = new StringBuilder()
if (feedDisplayType != null && !feedDisplayType.isEmpty()) {
sb.append(feedDisplayType)
sb.append(', ')
}
if (moduleType != null && !moduleType.isEmpty()) {
sb.append(moduleType)
sb.append(', ')
}
if (cellType != null && !cellType.isEmpty()) {
sb.append(cellType)
}
def presentationType = sb.toString()
,
as a delimiterdef presentationType = [feedDisplayType, moduleType, cellType].findAll { str -> str != null && !str.isEmpty() }.join(', ')
Before going into conclusion let's benchmark all 3 methods using GBench tool:
@Grab(group='org.gperfutils', module='gbench', version='0.4.3-groovy-2.4')
def feedDisplayType = 'test'
def moduleType = null
def cellType = ''
def r = benchmark {
'GString method' {
def presentationType = "${feedDisplayType != null && !feedDisplayType.isEmpty() ? feedDisplayType + ', ' : ''}${moduleType != null && !moduleType.isEmpty() ? moduleType + ', ' : ''}${cellType != null && !cellType.isEmpty() ? cellType : ''}".toString()
}
'StringBuilder method' {
def sb = new StringBuilder()
if (feedDisplayType != null && !feedDisplayType.isEmpty()) {
sb.append(feedDisplayType)
sb.append(', ')
}
if (moduleType != null && !moduleType.isEmpty()) {
sb.append(moduleType)
sb.append(', ')
}
if (cellType != null && !cellType.isEmpty()) {
sb.append(cellType)
}
def presentationType = sb.toString()
}
'Join list method' {
def presentationType = [feedDisplayType, moduleType, cellType].findAll { str -> str != null && !str.isEmpty() }.join(', ')
}
}
r.prettyPrint()
Environment
===========
* Groovy: 2.4.12
* JVM: OpenJDK 64-Bit Server VM (25.171-b10, Oracle Corporation)
* JRE: 1.8.0_171
* Total Memory: 236 MB
* Maximum Memory: 3497 MB
* OS: Linux (4.16.5-200.fc27.x86_64, amd64)
Options
=======
* Warm Up: Auto (- 60 sec)
* CPU Time Measurement: On
user system cpu real
GString method 265 2 267 268
StringBuilder method 72 4 76 77
Join list method 484 3 487 495
If you aim towards highest throughput, StringBuilder
method is the best one (77 nanoseconds mean time).
GString
method is a few times slower than StringBuilder
and it is much less readable due to all condition statements inside a single GString. It is also pretty error prone - it's easy to make a mistake when interpolating String in this case.
Joining list method is the slowest one (only 2 times slower approximately than GString method), but it is the cleanest one. And it is still pretty fast - 495 nanoseconds is acceptable in most cases. Of course optimization depends on specific use case - if you have to execute this part of code million times per second, then using StringBuilder
instead makes much more sense.
To make this example complete let's also take a look at corner cases in benchmarking. We use the same code with different input.
Input:
def feedDisplayType = 'lorem ipsum'
def moduleType = 'dolor sit amet'
def cellType = '123456789'
Output:
user system cpu real
GString method 387 1 388 390
StringBuilder method 170 0 170 175
Join list method 847 6 853 859
Input:
def feedDisplayType = ''
def moduleType = ''
def cellType = ''
Output:
user system cpu real
GString method 237 5 242 242
StringBuilder method 44 0 44 44
Join list method 441 0 441 446