Monday, September 28, 2009

Groovy JDK (GDK): String Support

In previous blog postings on the Groovy JDK (GDK), I discussed use of GDK File functions such as File.deleteDir(), File.getText(), File.readLines(), File.setText(String)/File.write(String), File.append(Object), and File.size(). In this blog post, I move onto covering the GDK's extended String class.

The GDK's extended String class has numerous convenience methods. These methods provide functionality that can often be implemented in custom Java code, but is handily available with the Groovy JDK.

The String.count(String) method counts the number of occurrences of the String passed as a parameter that exist within the String upon which the count method is called. A similar method that the extended String provides is the String.contains(String) method, which indicates whether the String upon which the method is invoked contains the String passed to the method as a parameter. Both of these methods are demonstrated in the next code listing.


// Demonstrate GDK's String.count() and String.contains(String)
repeatedString = "yesornoyesornoyesorno"
substr = "yes"
println "Number of occurrences of '${substr}' in $repeatedString: ${repeatedString.count(substr)}"
println "$repeatedString contains '$substr'?: ${repeatedString.contains(substr)}"


The output from this Groovy script snippet is shown next.



The method String.replace(String,String) allows a specified substring in the String to be replaced with the second specified String. This is demonstrated in the next code listing and its accompanying output screen snapshot.


// Demonstrate GDK's String.replace(CharSequence,CharSequence)
newSubstr = "si"
println "Replacing '$substr' in '$repeatedString' with '$newSubstr': ${repeatedString.replace(substr,newSubstr)}"




The overloaded versions of String.center() can be highly useful. The following snippet of Groovy code demonstrates the behavior of this centering method using various parameters. Spaces are used to center the provided text by default, but other characters can be used to force the centering as shown in this next code listing and its accompanying output screen snapshot.


// Demonstrate GDK's String.center(Number) and String.center(Number,String)
// 1. Demonstrate center with more characters than String being centered
// 2. Demonstrate center with fewer characters than String being centered
// 3. Demonstrate center with negative number of characters
// 4. Demonstrate center with characters other than spaces ("Groovy")
centeredString = "Dustin"
println "Centered String: 1. ${centeredString.center(20)}"
println "Centered String: 2. ${centeredString.center(4)}"
println "Centered String: 3. ${centeredString.center(-1)}"
println "Centered String: 4. ${centeredString.center(25,"Groovy")}"




The String.multiply(Number) method allows the target String to be multiplied as many times as specified by the passed-in parameter and returned as a single String. This is demonstrated in the following code with its output.


// Demonstrate String.multiply(Number)
multipleCopies = 5
println "Multiply '$centeredString' by $multipleCopies: ${centeredString.multiply(multipleCopies)}"


The GDK String extension provides several different methods for indicating whether a given String is of a particular numeric type. These can be useful to call before calling corresponding methods that convert the provided Strings to numeric types as well. The methods for determining if a String is of a particular numeric type are demonstrated next and the output is shown after the code listing.


// Demonstrate String methods for testing types of numerics
numericValue = "15";
alphaValue = "abc";
println "Is '$numericValue' parseable as a BigDecimal? ${numericValue.isBigDecimal()}"
println "Is '$alphaValue' parseable as a BigDecimal? ${alphaValue.isBigDecimal()}"
println "Is '$numericValue' parseable as a BigInteger? ${numericValue.isBigDecimal()}"
println "Is '$alphaValue' parseable as a BigInteger? ${alphaValue.isBigDecimal()}"
println "Is '$numericValue' parseable as a Double? ${numericValue.isDouble()}"
println "Is '$alphaValue' parseable as a Double? ${alphaValue.isDouble()}"
println "Is '$numericValue' parseable as a Long? ${numericValue.isLong()}"
println "Is '$alphaValue' parseable as a Long? ${alphaValue.isLong()}"
println "Is '$numericValue' parseable as a Float? ${numericValue.isFloat()}"
println "Is '$alphaValue' parseable as a Float? ${alphaValue.isFloat()}"
println "Is '$numericValue' parseable as a Number? ${numericValue.isNumber()}"
println "Is '$alphaValue' parseable as a Number? ${alphaValue.isNumber()}"




The GDK String extension provides methods String.readLines() and String.toList() to convert between a single String and multiple Strings. The readLines() method returns each distinct line in the given String as its own entry in a List of Strings. The toList() method converts each character in the target String to an element of a List of one-character entries.


// Demonstrate String.readLines() functionality
multiLineString = "One\nTwo\nThree\nFour\nFive"
println "Multiline String: $multiLineString"
println "Multiline String List: ${multiLineString.readLines()}"

// Demonstrate String.toList()
singleString = "123456789"
println "'$singleString'.toList() is ${singleString.toList()}"




The String.reverse() method does exactly what you'd think: it returns a String with the characters in reverse order of the original String.


// Demonstrate String.reverse()
println "'$singleString'.reverse() is ${singleString.reverse()}"




The String.getAt(int) method is useful for getting a character out of a String based on a particular index.


// Demonstrate String.getAt(int)
charIndex = 3
println "Character at index $charIndex is $singleString: ${singleString.getAt(3)}"




The String.leftShift(Object) method enables the << operator to be used to concatenate Strings into an overall String (or more precisely, a StringBuffer).


// Demonstrate left shift operator (String.leftShift(Object))
part1 = "Hello"
part2 = "World"
part3 = "Example"
concatenatedString = "$part1" << "$part2" << "$part3"
println "Concatenating $part1, $part2, and $part3: $concatenatedString"
println "Type of concatenatedString: ${concatenatedString.getClass().name}"




The String.minus(Object) method allows the String representation of the parameter Object to be removed from the target String. As noted in the previous example, the resultant "String" from use of the String.leftShift() method is actually a StringBuffer. The GDK does not provide the minus() method on StringBuffer so I need to explicitly inform Groovy that I am using a String to demonstrate the minus method on the just-concatenated "String."


// Demonstrate String.minus(Object)
//
// Need to tell Groovy to treat concatenatedStringOverall as a String rather
// than as a StringBuffer to be able to call the "minus" method. Otherwise, the
// error message encountered is:
// Caught: groovy.lang.MissingMethodException: No signature of method:
// java.lang.StringBuffer.minus() is applicable for argument types:
// (java.lang.String) values: [Example]
String concatenatedActualString = concatenatedString
println "Minus $part3 from $concatenatedActualString: ${concatenatedActualString.minus(part3)}"




The last convenience method on the GDK extended String class that I want to demonstrate is the handy (several overloaded versions) String.execute() method. This method allow the target String to be executed against the underlying operating system. This is demonstrated with the next code listing, which employs a Windows-specific command to list the directory contents.


// Demonstrate String.execute()
directoryListing = "cmd /C dir"
println "Directory Listing: ${directoryListing.execute().text}"


The output will, of course, vary per system, but looks something like that shown next:



This blog posting has demonstrated several useful functions provided by the Groovy JDK (GDK) extended String class. However, there are even more methods provided by this class than shown here. Like the rest of the GDK, the extended String class adds great convenience for the developer.

No comments: