| 1 Quick Start Guide to Groovy |
| |
| Groovy classes compile down to Java bytecode and so there's a 1-1 mapping between a Groovy class and a Java class. |
| Indeed each Groovy class can be used inside normal Java code - since it is a Java class too. |
| |
| Probably the easiest way to get groovy is to try working with collections. In Groovy List (java.util.List) and Map (java.util.Map) |
| are both first class objects in the syntax. So to create a List of objects you can do the following... |
| |
| {code:groovysh} |
| list = [1, 2, 'hello', new java.util.Date()] |
| assert list.size() == 4 |
| assert list.get(2) == 'hello' |
| {code} |
| |
| Notice that everything is an object (or that auto-boxing takes place when working with numbers). To create maps... |
| {code:groovysh} |
| map = ['name':'James', 'location':'London'] |
| assert map.size() == 2 |
| assert map.get('name') == 'James' |
| {code} |
| |
| Iterating over collections is easy... |
| {code:groovysh} |
| list = [1, 2, 3] |
| for (i in list) { println i } |
| {code} |
| |
| Once you have some collections you can then use some of the new collection helper methods or try working with closures... 1.1 Working with closures |
| |
| Closures are similar to Java's inner classes, except they are a single method which is invokable, with arbitrary parameters. |
| A closure can have as many parameters as you wish... |
| |
| {code:groovysh} |
| closure = { param | println("hello ${param}") } |
| closure.call("world!") |
| |
| closure = { greeting, name | println(greeting + name) } |
| closure.call("hello ", "world!") |
| {code} |
| |
| If no parameter(s) is(are) specified before the | symbol then a default named parameter, called 'it' can be used. e.g. |
| |
| {code:groovysh} |
| closure = { println "hello " + it } |
| closure.call("world!") |
| {code} |
| |
| Using closures allows us to process collections (arrays, maps, strings, files, SQL connections and so forth) in a clean way. |
| |
| Here are a number of helper methods available on collections & strings... 1.1.1 each |
| |
| iterate via a closure |
| |
| {code:groovysh} |
| [1, 2, 3].each { item | print "${item}-" } |
| {code} |
| |
| 1.1.1 collect |
| |
| collect the return value of calling a closure on each item in a collection |
| |
| {code:groovysh} |
| value = [1, 2, 3].collect { it * 2 } |
| assert value == [2, 4, 6] |
| {code} |
| |
| 1.1.1 find |
| |
| finds first item matching closure predicate |
| |
| {code:groovysh} |
| value = [1, 2, 3].find { it > 1 } |
| assert value == 2 |
| {code} |
| |
| 1.1.1 findAll |
| |
| finds all items matching closure predicate |
| |
| {code:groovysh} |
| value = [1, 2, 3].findAll { it > 1 } |
| assert value == [2, 3] |
| {code} |
| |
| 1.1.1 inject |
| |
| allows you to pass a value into the first iteration and then |
| pass the result of that iteration into the next iteration and so |
| on. This is ideal for counting and other forms of processing |
| |
| {code:groovysh} |
| value = [1, 2, 3].inject('counting: ') { str, item | str + item } |
| assert value == "counting: 123" |
| |
| value = [1, 2, 3].inject(0) { count, item | count + item } |
| assert value == 6 |
| {code} |
| |
| In addition there's 2 new methods for doing boolean logic on some collection... |
| |
| 1.1.1 every |
| |
| returns true if all items match the closure predicate |
| |
| {code:groovysh} |
| value = [1, 2, 3].every { it < 5 } |
| assert value |
| |
| value = [1, 2, 3].every { item | item < 3 } |
| assert ! value |
| {code} |
| |
| 1.1.1 any |
| |
| returns true if any item match the closure predicate |
| |
| {code:groovysh} |
| value = [1, 2, 3].any { it > 2 } |
| assert value |
| |
| value = [1, 2, 3].any { item | item > 3 } |
| assert value == false |
| {code} |
| |
| Other helper methods include 1.1.1 max / min |
| |
| returns the max/min values of the collection - for Comparable objects |
| |
| {code:groovysh} |
| value = [9, 4, 2, 10, 5].max() |
| assert value == 10 |
| value = [9, 4, 2, 10, 5].min() |
| assert value == 2 |
| value = ['x', 'y', 'a', 'z'].min() |
| assert value == 'a' |
| {code} |
| |
| 1.1.1 join |
| |
| concatenates the values of the collection together with a string value |
| |
| {code:groovysh} |
| value = [1, 2, 3].join('-') |
| assert value == '1-2-3' |
| {code} |
| |
| Also the 'yield' style of creating iterators, available in Python and |
| Ruby via the yield statement, is available. The only difference is |
| rather than using a yield statement, we're just using closures. |
| |
| {code:groovysh} |
| class Foo { |
| myGenerator(Closure yield) { |
| yield.call("A") |
| yield.call("B") |
| yield.call("C") |
| } |
| |
| static void main(args) { |
| foo = new Foo() |
| for (x in foo.myGenerator) { |
| println x |
| } |
| } |
| } |
| |
| foo = new Foo() |
| for (x in foo.myGenerator) { |
| print("${x}-") |
| } |
| {code} |
| |
| outputs |
| A-B-C- |
| |
| The use of Closure in the method prototype is optional. If we have |
| syntax sugar for invoking closures as if they are method calls, then |
| the generator method could look even more like the python/ruby |
| equivalent. Especially if parentheses are optional... |
| |
| {code:groovysh} |
| class Foo { |
| myGenerator(yield) { |
| yield "A" |
| yield "B" |
| yield("C") |
| } |
| |
| static void main(args) { |
| foo = new Foo() |
| foo.myGenerator { println "Called with ${it}" } |
| } |
| } |
| {code} |