Groovy Tutorial

Groovy TutorialI have made learn in one videos for most every language and today based on your requests I will teach Groovy in One Video. We’ll learn how to install on Mac and Windows. Then I’ll cover the Basics, Math, Strings, Output, Input, Lists, Maps, Range, Conditonals, Looping, Methods, Closures, File IO, OOP and a ton of other topics in between. By the end you’ll learn as much as you’d learn in a standard 250 page book on Groovy.

All of the code and a transcript of the video follows the video below. I hope you enjoy it.

If you enjoy videos like this, consider throwing a dollar my way on Patreon.

[googleplusone]

Code & Transcript From the Video

groovytut.groovy

/*
Install Groovy on Mac
1. Update Java to at least Java 7 in the System Preferences Java Control Panel

2. Type in Terminal /usr/libexec/java_home -V
to get something like
1.7.0_55, x86_64:	"Java SE 7"	/Library/Java/JavaVirtualMachines/jdk1.7.0_55.jdk/Contents/Home

3. Type in terminal export JAVA_HOME=`/usr/libexec/java_home -v 1.7.0_55, x86_64`

4. Type in terminal java -version and make sure you have at least Java 7

5. Install HomeBrew at http://brew.sh/

6. Type in terminal brew install groovy

7. In Atom Open Command Palette -> Install Packages Themes -> Type language-groovy and install

Install Groovy on Windows

1. Go here http://groovy-lang.org/download.html

2. Click Windows Installer and click next a bunch of times until it is installed.
*/

class GroovyTut {

// main is where execution starts
static void main(String[] args){

  // Print to the screen
  println("Hello World");

  // ---------- MATH ----------
  // Everything in Groovy is an object
  // including numbers

  // def is used when you define a variable
  // Variables start with a letter and can
  // contain numbers and _
  // Variables are cynamically typed and can
  // hold any value
  def age = "Dog";
  age = 40;

  // The basic integer math operators
  println("5 + 4 = " + (5 + 4));
  println("5 - 4 = " + (5 - 4));
  println("5 * 4 = " + (5 * 4));
  println("5 / 4 = " + (5.intdiv(4)));
  println("5 % 4 = " + (5 % 4));

  // Floating point math operators
  println("5.2 + 4.4 = " + (5.2.plus(4.4)));
  println("5.2 - 4.4 = " + (5.2.minus(4.4)));
  println("5.2 * 4.4 = " + (5.2.multiply(4.4)));
  println("5.2 / 4.4 = " + (5.2 / 4.4));

  // Order of operations
  println("3 + 2 * 5 = " + (3 + 2 * 5));
  println("(3 + 2) * 5 = " + ((3 + 2) * 5));

  // Increment and decrement
  println("age++ = " + (age++));
  println("++age = " + (++age));
  println("age-- = " + (age--));
  println("--age = " + (--age));

  // Largest values
  println("Biggest Int " + Integer.MAX_VALUE);
  println("Smallest Int " + Integer.MIN_VALUE);

  println("Biggest Float " + Float.MAX_VALUE);
  println("Smallest Float " + Float.MIN_VALUE);

  println("Biggest Double " + Double.MAX_VALUE);
  println("Smallest Double " + Double.MIN_VALUE);

  // Decimal Accuracy
  println("1.1000000000000001 + 1.1000000000000001 "
  + (1.1000000000000001111111111111111111111111111111111111 + 1.1000000000000001111111111111111111111111111111111111));

  // Math Functions
  def randNum = 2.0;
  println("Math.abs(-2.45) = " + (Math.abs(-2.45)));
  println("Math.round(2.45) = " + (Math.round(2.45)));
  println("randNum.pow(3) = " + (randNum.pow(3)));
  println("3.0.equals(2.0) = " + (3.0.equals(2.0)));
  println("randNum.equals(Float.NaN) = " + (randNum.equals(Float.NaN)));
  println("Math.sqrt(9) = " + (Math.sqrt(9)));
  println("Math.cbrt(27) = " + (Math.cbrt(27)));
  println("Math.ceil(2.45) = " + (Math.ceil(2.45)));
  println("Math.floor(2.45) = " + (Math.floor(2.45)));
  println("Math.min(2,3) = " + (Math.min(2,3)));
  println("Math.max(2,3) = " + (Math.max(2,3)));

  // Number to the power of e
  println("Math.log(2) = " + (Math.log(2)));

  // Base 10 logarithm
  println("Math.log10(2) = " + (Math.log10(2)));

  // Degrees and radians
  println("Math.toDegrees(Math.PI) = " + (Math.toDegrees(Math.PI)));
  println("Math.toRadians(90) = " + (Math.toRadians(90)));

  // sin, cos, tan, asin, acos, atan, sinh, cosh, tanh
  println("Math.sin(0.5 * Math.PI) = " + (Math.sin(0.5 * Math.PI)));

  // Generate random value from 1 to 100
  println("Math.abs(new Random().nextInt() % 100) + 1 = " + (Math.abs(new Random().nextInt() % 100) + 1));

  // ---------- STRINGS ----------

  def name = "Derek";

  // A string surrounded by single quotes is taken literally
  // but backslashed characters are recognized
  println('I am ${name}\n');
  println("I am $name\n");

  // Triple quoted strings continue over many lines
  def multString = '''I am
  a string
  that goes on
  for many lines''';

  println(multString);

  // You can access a string by index
  println("3rd Index of Name " + name[3]);
  println("Index of r " + name.indexOf('r'));

  // You can also get a slice
  println("1st 3 Characters " + name[0..2]);

  // Get specific Characters
  println("Every Other Character " + name[0,2,4]);

  // Get characters starting at index
  println("Substring at 1 " + name.substring(1));

  // Get characters at index up to another
  println("Substring at 1 to 4 " + name.substring(1,4));

  // Concatenate strings
  println("My Name " + name);
  println("My Name ".concat(name));

  // Repeat a string
  def repeatStr = "What I said is " * 2;
  println(repeatStr);

  // Check for equality
  println("Derek == Derek : " + ('Derek'.equals('Derek')));
  println("Derek == derek : " + ('Derek'.equalsIgnoreCase('derek')));

  // Get length of string
  println("Size " + repeatStr.length());

  // Remove first occurance
  println(repeatStr - "What");

  // Split the string
  println(repeatStr.split(' '));
  println(repeatStr.toList());

  // Replace all strings
  println(repeatStr.replaceAll('I', 'she'));

  // Uppercase and lowercase
  println("Uppercase " + name.toUpperCase());
  println("Lowercase " + name.toLowerCase());

  // <=> returns -1 if 1st string is before 2nd
  // 1 if the opposite and 0 if equal
  println("Ant <=> Banana " + ('Ant' <=> 'Banana'));
  println("Banana <=> Ant " + ('Banana' <=> 'Ant'));
  println("Ant <=> Ant " + ('Ant' <=> 'Ant'));

  // ---------- OUTPUT ----------
  // With double quotes we can insert variables
  def randString = "Random";
  println("A $randString string");

  // You can do the same thing with printf
  printf("A %s string \n", randString);

  // Use multiple values
  printf("%-10s %d %.2f %10s \n", ['Stuff', 10, 1.234, 'Random']);

  /*

  // ---------- INPUT ----------
  print("Whats your name ");
  def fName = System.console().readLine();
  println("Hello " + fName);

  // You must cast to the right value
  // toInteger, toDouble
  print("Enter a number ");
  def num1 = System.console().readLine().toDouble();
  print("Enter another ");
  def num2 = System.console().readLine().toDouble();
  printf("%.2f + %.2f = %.2f \n", [num1, num2, (num1 + num2)]);

  */

  // ---------- LISTS ----------
  // Lists hold a list of objects with an index

  def primes = [2,3,5,7,11,13];

  // Get a value at an index
  println("2nd Prime " + primes[1]);
  println("3rd Prime " + primes.get(2));

  // They can hold anything
  def employee = ['Derek', 40, 6.25, [1,2,3]];

  println("2nd Number " + employee[3][1]);

  // Get the length
  println("Length " + primes.size());

  // Add an index
  primes.add(17);

  // Append to the right
  primes<<19;
  primes.add(23);

  // Concatenate 2 Lists
  primes + [29,31];

  // Remove the last item
  primes - [31];

  // Check if empty
  println("Is empty " + primes.isEmpty());

  // Get 1st 3
  println("1st 3 " + primes[0..2]);

  println(primes);

  // Get matches
  println("Matches " + primes.intersect([2,3,7]));

  // Reverse
  println("Reverse " + primes.reverse());

  // Sorted
  println("Sorted " + primes.sort());

  // Pop last item
  println("Last " + primes.pop());

  // ---------- MAPS ----------
  // List of objects with keys versus indexes

  def paulMap = [
    'name' : 'Paul',
    'age' : 35,
    'address' : '123 Main St',
    'list' : [1,2,3]
  ];

  // Access with key
  println("Name " + paulMap['name']);
  println("Age " + paulMap.get('age'));
  println("List Item " + paulMap['list'][1]);

  // Add key value
  paulMap.put('city', 'Pittsburgh');

  // Check for key
  println("Has City " + paulMap.containsKey('city'));

  // Size
  println("Size " + paulMap.size());

  // ---------- RANGE ----------
  // Ranges represent a range of values in shorthand notation

  def oneTo10 = 1..10;
  def aToZ = 'a'..'z';
  def zToA = 'z'..'a';

  println(oneTo10);
  println(aToZ);
  println(zToA);

  // Get size
  println("Size " + oneTo10.size());

  // get index
  println("2nd Item " + oneTo10.get(1));

  // Check if range contains
  println("Contains 11 " + oneTo10.contains(11));

  // Get last item
  println("Get Last " + oneTo10.getTo());

  println("Get First " + oneTo10.getFrom());

  // ---------- CONDITIONALS ----------
  // Conditonal Operators : ==, !=, >, <, >=, <=

  // Logical Operators : && || !

  def ageOld = 6;

  if(ageOld == 5){
    println("Go to Kindergarten");
  } else if((ageOld > 5) && (ageOld < 18)) {
    printf("Go to grade %d \n", (ageOld - 5));
  } else {
    println("Go to College");
  }

  def canVote = true;

  // Ternary operator
  println(canVote ? "Can Vote" : "Can't Vote");

  // Switch statement
  switch(ageOld) {
    case 16: println("You can drive");
    case 18:
      println("You can vote");

      // Stops checking the rest if true
      break;
    default: println("Have Fun");
  }

  // Switch with list options
  switch(ageOld){
    case 0..6 : println("Toddler"); break;
    case 7..12 : println("Child"); break;
    case 13..18 : println("Teenager"); break;
    default : println("Adult");
  }

  // ---------- LOOPING ----------
  // While loop

  def i = 0;

  while(i < 10){

    // If i is odd skip back to the beginning of the loop
    if(i % 2){
      i++;
      continue;
    }

    // If i equals 8 stop looping
    if(i == 8){
      break;
    }

    println(i);
    i++;
  }

  // Normal for loop
  for (i = 0; i < 5; i++) {
    println(i);
  }

  // for loop with a range
  for(j in 2..6){
    println(j);
  }

  // for loop with a list (Same with string)
  def randList = [10,12,13,14];

  for(j in randList){
    println(j);
  }

  // for loop with a map
  def custs = [
    100 : "Paul",
    101 : "Sally",
    102 : "Sue"
  ];

  for(cust in custs){
    println("$cust.value : $cust.key ");
  }

  // ---------- METHODS ----------
  // Methods allow us to break our code into parts and also
  // allow us to reuse code

  sayHello();

  // Pass parameters
  println("5 + 4 = " + getSum(5,4));

  // Demonstrate pass by value
  def myName = "Derek";
  passByValue(myName);
  println("In Main : " + myName);

  // Pass a list for doubling
  def listToDouble = [1,2,3,4];
  listToDouble = doubleList(listToDouble);
  println(listToDouble);

  // Pass unknown number of elements to a method
  def nums = sumAll(1,2,3,4);
  println("Sum : " + nums);

  // Calculate factorial (Recursion)
  def fact4 = factorial(4);
  println("Factorial 4 : " + fact4);

  // ---------- CLOSURES ----------
  // Closures represent blocks of code that can except parameters
  // and can be passed into methods.

  // Alternative factorial using a closure
  // num is the excepted parameter and call can call for
  // the code to be executed
  def getFactorial = { num -> (num <= 1) ? 1 : num * call(num - 1) }
  println("Factorial 4 : " + getFactorial(4));

  // A closure can access values outside of it
  def greeting = "Goodbye";
  def sayGoodbye = {theName -> println("$greeting $theName")}

  sayGoodbye("Derek");

  // each performs an operation on each item in list
  def numList = [1,2,3,4];
  numList.each { println(it); }

  // Do the same with a map
  def employees = [
    'Paul' : 34,
    'Sally' : 35,
    'Sam' : 36
  ];

  employees.each { println("${it.key} : ${it.value}"); }

  // Print only evens
  def randNums = [1,2,3,4,5,6];
  randNums.each {num -> if(num % 2 == 0) println(num);}

  // find returns a match
  def nameList = ['Doug', 'Sally', 'Sue'];
  def matchEle = nameList.find {item -> item == 'Sue'}
  println(matchEle);

  // findAll finds all matches
  def randNumList = [1,2,3,4,5,6];
  def numMatches = randNumList.findAll {item -> item > 4}
  println(numMatches);

  // any checks if any item matches
  println("> 5 : " + randNumList.any {item -> item > 5});

  // every checks that all items match
  println("> 1 : " + randNumList.every {item -> item > 1});

  // collect performs operations on every item
  println("Double : " + randNumList.collect { item -> item * 2});

  // pass closure to a method
  def getEven = {num -> return(num % 2 == 0)}
  def evenNums = listEdit(randNumList, getEven);
  println("Evens : " + evenNums);

  // ---------- FILE IO ----------

  // Open a file, read each line and output them
  new File("test.txt").eachLine {
    line -> println "$line";
  }

  // Overwrite the file
  new File("test.txt").withWriter('utf-8') {
    writer -> writer.writeLine("Line 4");
  }

  // Append the file
  File file = new File("test.txt");
  file.append('Line 5');

  // Get the file as a string
  println(file.text);

  // Get the file size
  println("File Size : ${file.length()} bytes");

  // Check if a file or directory
  println("File : ${file.isFile()}");
  println("Dir : ${file.isDirectory()}");

  // Copy file to another file
  def newFile = new File("test2.txt");
  newFile << file.text;

  // Delete a file
  newFile.delete();

  // Get directory files
  def dirFiles = new File("").listRoots();
  dirFiles.each {
    item -> println file.absolutePath;
  }

  // ---------- OOP ----------
  // Classes are blueprints that are used to define objects
  // Every object has attributes (fields) and capabilities
  // (methods)

  // Create an Animal object with named parameters
  // def king = new Animal(name : 'King', sound : 'Growl');
  // or with a Constructor
  def king = new Animal('King', 'Growl');

  println("${king.name} says ${king.sound}");

  // Change an object attribute with a setter
  king.setSound('Grrrr');
  println("${king.name} says ${king.sound}");

  king.run();

  println(king.toString());

  // With inheritance a class can inherit all fields
  // and methods of another class
  def grover = new Dog('Grover', 'Grrrrr', 'Derek');

  king.makeSound();
  grover.makeSound();

  // Mammal inherits from the abstract class Thing
  def hamster = new Mammal('Furry');
  hamster.getInfo();

  // ---------- EXCEPTION HANDLING ----------
  // Handles runtime errors

  try {
    File testFile;
    testFile.append('Line 5');
  }
  catch(NullPointerException ex){

    // Prints exception
    println(ex.toString());

    // Prints error message
    println(ex.getMessage());
  }
  catch(Exception ex){
    println("I Catch Everything");
  }
  finally {
    println("I perform clean up")
  }


}

// ---------- METHODS ----------

// Define them with def and static which means it is shared
// by all instances of the class
static def sayHello() {
  println("Hello");
}

// Methods can receive parameters that have default values
static def getSum(num1=0, num2=0){
  return num1 + num2;
}

// Any object passed to a method is pass by value
static def passByValue(name){

  // name here is local to the function and can't
  // be accessed outside of it
  name = "In Function";
  println("Name : " + name);
}

// Receive and return a list
static def doubleList(list){

  // Collect performs a calculation on every item in the list
  def newList = list.collect { it * 2};
  return newList;
}

// Pass unknown number of elements to a method
static def sumAll(int... num){
  def sum = 0;

  // Performs a calculation on every item with each
  num.each { sum += it; }
  return sum;
}

// Calculate factorial (Recursion)
static def factorial(num){
  if(num <= 1){
    return 1;
  } else {
    return (num * factorial(num - 1));
  }
}

// 1st: num = 4 * factorial(3) = 4 * 6 = 24
// 2nd: num = 3 * factorial(2) = 3 * 2 = 6
// 3rd: num = 2 * factorial(1) = 2 * 1 = 2

// ---------- CLOSURES ----------
// pass closure to a method

static def listEdit(list, clo){
  return list.findAll(clo);
}

}

Animal.groovy

import groovy.transform.ToString;

// Creates the toString method
@ToString(includeNames=true, includeFields=true)
class Animal {
  // Fields (Attributes)
  def name;
  def sound;

  // Methods (Capabilites)

  def run(){
    println("${name} runs");
  }

  def makeSound(){
    println("${name} says ${sound}");
  }

  // Constructor Method
  def Animal(name, sound){
    this.name = name;
    this.sound = sound;
  }


}

Dog.groovy

class Dog extends Animal{
  def owner;

  // Constructor Method
  def Dog(name, sound, owner){

    // Call the Animal constructor
    super(name, sound);
    this.owner = owner;
  }

  // Overwrite the Animal makeSound()
  def makeSound(){
    println("${name} says bark and ${sound}");
  }
}

Thing.groovy

// An Abstract class can't be instantiated, but it
// can contain fields, and abstract or concrete methods

abstract class Thing{
  public String name;
  public Thing() {}

  def getInfo(){
    println("The things name is ${name}");
  }
}

Mammal.groovy

class Mammal extends Thing{
  def Mammal(name){
    this.name = name;
  }
}

Widget.groovy

// An interface defines a contract that says any
// object that inherits from it will implement
// the methods defined by it
// All methods are abstract
class Widget {

  // Define abstract method that returns nothing
  void doSomething();
}

One thought on “Groovy Tutorial”

  1. I saw a few typos in the comments:

    math section “cynamically”-> “dynamically”
    closures section “except” -> “accept”

Leave a Reply

Your email address will not be published. Required fields are marked *