Introduction to Groovy

October 3, 2015

by Jenn Strater @jennstrater

Current

http://jlstrater.github.io/intro-groovy-osn

Slides(source)

About Me

Professional

About Me

Experience

source: http://tjvantoll.com/2014/12/29/so-you-want-to-write-a-tech-book/

About Me

Minneapolis, MN

    Connect on Social Media
  • Twitter @jennstrater
  • LinkedIn https://linkedin.com/in/jennstrater
  • Github https://github.com/jlstrater

About YOU

  • Students
  • Professional Developers
    • Java
    • .NET
    • PHP or Ruby
    • JRuby, Scala, or Clojure
    • Groovy

Agenda

  • Background & Ecosystem
  • Getting Started
  • Concepts
    • Data Types
    • Collections/Loops
    • Functions
    • Closures

Agenda

  • Object Oriented Programming (OOP)
  • Scripting
  • File Processing
  • APIs

Groovy

  • Dynamic, compiled language for the Java Virtual Machine(JVM).
  • Interoperable with existing Java libraries
  • Concise, easy to read code
  • Used by many major companies including:

Open Source

Apache

http://groovy-lang.org

To contribute: https://github.com/apache/incubator-groovy

The Groovy Ecosystem

When to use Groovy

  • existing Java libraries
  • developers know Java or another JVM language
  • infrastructure to support JVMs
  • quick prototyping
  • scripting
  • writing tests

When Not to use Groovy

  • lots of legacy code in another language
  • need 'bare metal' level performance

Getting Started

Groovy Shell

Groovy Console

Web Console

http://groovyconsole.appspot.com/

Things to Remember

  1. There is more than one way to do almost anything.
  2. It's probably optional.
    • semi-colons
    • typing
    • parenthesis around parameters
    • return statements
  3. By default, the last command executed is what's returned.

Hello, World!

groovy>println "Hello, Open Source North!"

Hello, Open Source North!
===>null

Data Types

  • Optional Typing, NOT dynamic
  • treated as objects
    • int treated like Integer
int i = 10
println i.class.name
 -> java.lang.Integer
 
Integer i = 20
println i.class.name
 -> java.lang.Integer

def

when no type is specified or for a flexible type

def i = 10
println i * 2
 -> 20
 
i = 'abc'
println i * 2
 -> abcabc

Strings

(examples in console)

  • Single Quoted
  • Double Quoted
  • Multi-line

Collections

Lists

(examples in console)

  • definition
  • get/set values
  • append
  • multiply
List m = ['a', 'b', 2]
println m[2]
-> 2

m[2] = 3
println m
-> [a, b, 3]

m << 'c'
println m
-> [a, b, 3, c]

m.push(4)
-> [a, b, 3, c, 4]

m.pop()
-> 4
List m = ['a', 'b', 2]

m.multiply(2)
 -> ['a', 'b', 2, 'a', 'b', 2]
 
m * 2
 -> ['a', 'b', 2, 'a', 'b', 2]
 
m + 2
 -> ['a', 'b', 2, 2]

Maps

(examples in console)

  • definition
  • get/set values
  • get all keys/values
Map m = [val1: 'a', val2: 'b', val3: 2]

println m.val1
 -> a
println m['val3']
 -> 2
 
m.val4 = 3
println m
 -> [val1:a, val2:b, val3: 2, val4: 3]
 
println m.keySet()
 -> [val1, val2, val3, val4]
 
println m.values()
 -> [a, b, 2, 3]

Ranges

println (1..10)
  -> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
println (1..<10)
  -> [1, 2, 3, 4, 5, 6, 7, 8, 9]

Functions

Integer timesTwo(x) {
  x + x
}
  • Flexible, familiar syntax
  • Optional
    • Parenthesis when calling functions
    • Parameter typing
    • return statements
println timesTwo(10)
 -> 20
def result = timesTwo 10
println result
 -> 20

Closures

Code as Data

(to the console)

  • definition
  • calls
Closure c = { name, year = 2015 ->
  println "Hello, $name $year!"
}

c.call('Open Source North')
-> "Hello, Open Source North 2015!"

c('Open Source North', 2016)
-> "Hello, Open Source North 2016"

Loops and Special Functions

  • Basic For Loop
  • Each
  • Collect
  • Spread Dot

Basic Loops

List dl = []

for(Integer i = 1; i < 4; i++){
  dl.add(i * 2)
}

println dl
 -> [2, 4, 6]
List dl = []

for(i in [1,2,3]) {
  dl << i * 2
}

println dl
 -> [2, 4, 6]

Each

List sl = [1, 2, 3]
List dl = []
sl.each { it ->
  dl << it * 2
}
println dl
-> [2, 4, 6]

Collect

Map m = [va1: 1, var2: 2, var3: 3]

List dl = m.collect { key, value ->
  value * 2
}

println dl
 -> [2, 4, 6]

Spread Dot

(1..3).multiply(2) -> [1, 2, 3, 1, 2, 3](1..3)*.multiply(2) -> [2, 4, 6]

Try It!

Print the sum of the numbers from 1 to 10

option 1:
Integer answer = 0
for(i in [1,2,3,4,5,6,7,8,9,10]) {
  answer += i
}
println answer
option 2:
Integer answer = 0
(1..10).each {
  answer = answer + it
}
println answerbonus answer:
println (1..10).sum()

Groovy Truth

False values

  • null
  • Empty Set
  • Empty String
  • Zero

Equality

== verifies value

is verifies object identity

List numbers = [0,1,2,3]
numbers.each {
  if(it) {
    println it
  }
}

-> 1
-> 2
-> 3

Other Groovy Operators

  • Ternary Operator
  • x ? return x : return 'something else'
  • Elvis Operator
  • x ?: 'something else'
  • Null Safe
  • myMap?.propertyA?.propertyB

Search

Map m = [val1: 2, val2: 4, val3: 6]

m.find { it.value % 2 == 0 && it.value % 3 != 0 }
-> val1=2

m.findAll {it.value % 2 == 0 && it.value % 3 != 0 }
-> [val1:2, val2:4]

Other List Methods

  • Any
  • Map m = [val1: 2, val2: 4, val3: 6]
    m.any { it.value % 2 == 0 }
    -> true
  • Every
  • m.every { it.value % 3 == 0 }
    -> false

Object Oriented Programming (OOP)

class Person {
  String first
  String last
}
Person me = new Person(first: 'Jenn', last: 'Strater')
println me.first
println me.last

-- add String company to class --
me.company = 'Object Partners'
println me.properties
-> [class:class Person, first:Jenn, company:Object Partners, last:Strater]
class Person {
  String first
  String last
  
  String getFullName() {
    this.first + ' ' + this.last
  }
}

Person me = new Person(first: 'Jenn', last: 'Strater')
println me.fullName
 -> 'Jenn Strater'

Scripts

(save previous script as people.groovy)

groovy people.groovy
-> Jenn Strater

Script Parsing

println doubledValue(10)

def doubledValue(x) {
  x * 2
}

File Processing

Creating and Writing to Files

def myFile = new File('foo.txt')
myFile.write 'Hello, \n'
myFile.append('Open Source North!')

foo.txt

Hello,
Open Source North!

Reading Files

def myFile = new File('foo.txt')
myFile.eachLine { line ->
  def processedLine = line.replaceAll('Hello', 'Hi')
  println processedLine
}

 -> Hi,
 -> Open Source North!

APIs

(copy to console)

@Grab(group='org.codehaus.groovy.modules.http-builder', module='http-builder', version='0.7.1')
import groovyx.net.http.RESTClient
def http = new RESTClient("http://www.gr8ladies.org")
http.get(path: '/api/companies') { resp, reader ->
  reader.sort { -it.percentageTotalWomen } // sort by percentage women in descending order
  reader[0..4].each{ // only the first 5
    if(it.totalEmployees) { // if the value of total employees is not 0 (to eliminate companies that didn't report that field)
      println 'name:' + it.name
      println 'country:' + it.country
      println 'total employees: ' + it.totalEmployees
      println 'total men: '+ it.totalMen
      println 'total women: '+ it.totalWomen + '\n'
    }
  }
}
return null // don't print the entire result at the end

APIs

(copy to console)

@Grab(group='org.codehaus.groovy.modules.http-builder', module='http-builder', version='0.7.1')

import groovyx.net.http.RESTClient

def http = new RESTClient("http://api.icndb.com")

http.get(path: '/jokes/random/5', query: [exclude: 'explicit']) { resp, reader ->
  reader.value.joke.each{
    println it + '\n'
  }
}

Other Cool Groovy Things

  • Regex
  • MetaClass
  • Groovy for Android
  • Compile Static Annotation

Conclusions

    Groovy
  • provides the benefits of the JVM platform
  • adds features to enhance productivity over Java
  • is similar to other languages such as Ruby and Python

References

Questions?

@jennstrater

jenn@gr8ladies.org