Groovy es un lenguaje de programación ágil y dinámico diseñado para la Plataforma Java con determinadas características inspiradas en lenguajes como Python, Ruby o Smalltalk, poniéndolas a disposición de los programadores Java mediante una sintaxis típica de Java.
public class ListFiles {
public static void main(String[] args){
new java.io.File(".").eachFileRecurse(
new FileListener() {
public void onFile (File file) {
System.out.println(file.toString());
}
}
);
}
}
groovy -e "new File('.').eachFileRecurse { println it}"
curl -s get.gvmtool.net | bash
gvm list groovy
gvm install groovy 2.4.0
Podríamos cambiar la instalación con:
gvm use groovy 1.8.0
Tenemos 3 formas de ejecutar código Groovy
Permite ejecutar en línea de comandos código Groovy de forma interactiva. Más información en http://groovy.codehaus.org/Groovy+Shell.
groovy:000> "Hola Mundo!"
groovy:000> saludo = "Hola" ===> Hola groovy:000> "${saludo} Mundo!" ===> Hola Mundo!
groovy:000> def hola(nombre){
groovy:001> println "Hola $nombre"
groovy:002> }
===> true
groovy:000> hola("Fran")
Hola Fran
==== > null
Interfaz Swing que actua como intérprete de comandos Groovy. Permite guardar y cargar archivos. Más información en http://groovy.codehaus.org/Groovy+Console.
java -cp $GROOVY_HOME/embeddable/groovy-all-2.4.0.jar:classes fibonacci
Aspectos comunes:
Groovy añade valor a:
assert(true)
assert 1 == 1
def x = 1
assert x == 1
def y = 1; assert y == 1
assert 1==2 : "Desde cuando 1 es igual a 2"
//Obteniendo el siguiente mensaje
//Exception thrown: Desde cuando 1 es igual a 2. Expression: (1 == 2)
assert new File('foo.bar') == new File('example.txt')
Exception thrown
Assertion failed:
assert new File('foo.bar') == new File('example.txt')
| | |
foo.bar | example.txt
false
class Libro {
private String titulo
Libro (String elTitulo){
titulo = elTitulo
}
String getTitulo(){
return titulo
}
}
Libro cgg = new Libro('Curso GroovyGrails')
assert cgg.getTitulo() == 'Curso GroovyGrails'
assert getTituloAlReves(cgg) == 'sliarGyvoorG osruC'
String getTituloAlReves(libro) {
titulo = libro.getTitulo()
return titulo.reverse()
}
class Libro{
String titulo;
String getTitulo(){
return this.titulo
}
void setTitulo(String str){
this.titulo = new String(str)
}
}
def x = 1
def y = 2
assert x + y == 3
assert x.plus(y) == 3
assert x instanceof Integer
double d = 10.23
assert d instanceof Double
char a = 'a'
assert a instanceof Character
if (foo.is(bar))
println "foo y bar son el mismo objeto"
def a = true
def b = true
def c = false
assert a
assert a && b
assert a || c
assert !c
def numeros = [1,2,3]
assert numeros //cierto, ya que numeros no está vacía
numeros = [] //vacíamos la lista
assert !numeros //cierto, ya que ahora la lista está vacía
assert ['one':1] //este mapa contiene un elemento con lo que se evalúa a cierto
assert ![:] //este mapa está vacío
assert 'Esto es cierto'
assert !''
//GStrings
def s = ''
assert !("$s")
s = 'x'
assert ("$s")
assert !0
assert 1
assert new Object()
assert !null
if ( ... ) {
...
} else if (...) {
...
} else {
...
}
def y = 5
def x = (y > 1) ? "funciona" : "falla"
assert x == "funciona"
def usuario = [nombre:"Fran"]
def nombre = usuario.nombre ?: "Anónimo"
assert nombre == "Fran"
usuario = [:]
nombre = usuario.nombre ?: "Anónimo"
assert nombre == "Anónimo"
def x = 1.23
def result = ""
switch ( x ) {
case "foo":
result = "found foo"
// lets fall through
case "bar":
result += "bar"
case [4, 5, 6, 'inList']:
result = "list"
break
case 12..30:
result = "range"
break
case Integer:
result = "integer"
break
case Number:
result = "number"
break
default:
result = "default"
}
assert result == "number"
Utiliza la anotación for (i in x) { cuerpo } donde x puede ser cualquier cosa que se puede iterar.
for(i in 1..10)
println i
for(i in [1,2,3,4,5,6,7,8,9,10])
println i
def alumnos = ['Pedro','Miguel','Alejandro','Elena']
alumnos.each{nombre -> println nombre}
ArrayList resultados = new ArrayList();
for (int i=0; i < listaUno.size(); i++){
Integer primero = (Integer)listaUno.get(i);
Integer segundo = (Integer)listaDos.get(i);
int suma = primero.intValue() + segundo.intValue();
resultados.add(new Integer(suma));
}
ArrayList resultados = new ArrayList();
for (int i=0; i < listaUno.size(); i++){
resultados.add(primero + segundo)
}
Tipo primitivo | Tipo referencia |
---|---|
byte | java.lang.Byte |
short | java.lang.Short |
int | java.lang.Integer |
long | java.lang.Long |
float | java.lang.Float |
double | java.lang.Double |
char | java.lang.Character |
boolean | java.lang.Boolean |
Sólo se hace autoboxing cuando sea estrictamente necesario
assert 'Hola Mundo'.indexOf(111) == 1
assert 1 + 2 == 3 //1.plus(2)
Sentencia | Tipo de variable |
---|---|
def a = 2 | java.lang.Integer |
def b = 0.4f | java.lang.Float |
def c = 'a' | java.lang.String |
int d = 3 | java.lang.Integer |
float e = 4 | java.lang.Float |
char f = '1' | java.lang.Character |
Integer g = 6 | java.lang.Integer |
String h = '1' | java.lang.String |
Character i = 'a' | java.lang.Character |
def a = 2
def b = 0.4f
def c = 'a'
int d = 3
float e = 4
char f = '1'
Integer g = 6
String h = '1'
Character i = 'a'
assert a instanceof java.lang.Integer
assert b instanceof java.lang.Float
assert c instanceof java.lang.String
assert d instanceof java.lang.Integer
assert e instanceof java.lang.Float
assert f instanceof java.lang.Character
assert g instanceof java.lang.Integer
assert h instanceof java.lang.String
assert i instanceof java.lang.Character
def nombre = "Fran"
assert "hola $nombre" == "hola Fran"
Varias formas de crear cadenas de texto
def c1 = 'hola Juan'
def c2 = "hola $nombre"
def c3 = '''-------------
Total:0.02
-------------'''
def c4 = """-------------
Total:$total
-------------"""
def c5 = /x(\d*)y/
nombre = 'Fran'
apellidos = 'García'
salida = "Apellidos, nombre: $apellidos, $nombre"
fecha = new Date(0)
salida = "Año $fecha.year, Mes $fecha.month, Día $fecha.date"
salida = "La fecha es ${fecha.toGMTString()}"
sentenciasql = """
SELECT nombre, apellidos
FROM usuarios
WHERE anyo_nacimiento=$fecha.year
"""
saludo = 'Hola Juan'
assert saludo.startsWith('Hola')
assert saludo.getAt(3) == 'a'
assert saludo[3] == 'a'
assert saludo.indexOf('Juan') == 5
assert saludo.contains('Juan')
assert saludo[5..8] == 'Juan'
assert 'Buenos días' + saludo - 'Hola' == 'Buenos días Juan'
assert saludo.count('a') == 2
assert 'b'.padLeft(3) == ' b'
assert 'b'.padRight(3,'_') == 'b__'
assert 'b'.center(3) == ' b '
assert 'b' * 3 == 'bbb'
Símbolo | Significado |
---|---|
. | Cualquier carácter |
^ | El inicio de una línea |
$ | El final de una línea |
\d | Un dígito |
\D | Cualquier cosa excepto un dígito |
\s | Un espacio en blanco |
\S | Cualquier cosa excepto un espacio en blanco |
\w | Un carácter de texto |
\W | Cualquier carácter excepto los de texto |
\b | Límite de palabras |
() | Agrupación |
(x\|y) | O x o y |
x* | Cero o más ocurrencias de x |
x+ | Una o más ocurrencias de x |
x? | Cero o una ocurrencia de x |
x{m,n} | Entre m y n ocurrencias de x |
x{m} | Exactamente m ocurrencias de x |
[a-d] | Incluye los caracteres a, b, c y d |
[^a] | Cualquier carácter excepto la letra a |
refran = "tres tristes tigres tigraban en un tigral"
//Compruebo que hay al menos un fragmento de código que empieza por t,
//le siga cualquier caracter y posteriormente haya una g
assert refran =~ /t.g/
//Compruebo que el refrán esté compuesto sólo
//por palabras seguidas de un espacio
assert refran ==~ /(\w+ \w+)*/
//Compruebo que el valor de una operación de tipo match es un booleano
assert (refran ==~ /(\w+ \w+)*/) instanceof java.lang.Boolean
//A diferencia que una operación de tipo find,
//las operaciones match se evalúan por completo contra una cadena
assert (refran ==~ /t.g/) == false
//Sustituyo las palabras por el caracter x
assert (refran.replaceAll(/\w+/,'x')) == 'x x x x x x x'
//Devuelve un array con todas las palabras del refrán
palabras = refran.split(/ /)
assert palabras.size() == 7
assert palabras[2] == 'tigres'
assert palabras.getAt(3) == 'tigraban'
refran = "tres tristes tigres tigraban en un tigral"
//Busco todas las palabras que acaben en 'es'
rima = ~/\b\w*es\b/
resultado = ''
refran.eachMatch(rima) { match ->
resultado += match + ' '
}
assert resultado == 'tres tristes tigres '
//Hago lo mismo con el método each
resultado = ''
(refran =~ rima).each { match ->
resultado += match + ' '
}
assert resultado == 'tres tristes tigres '
//Sustituyo todas las rimas por guiones bajos
assert (refran.replaceAll(rima){ it-'es'+'__'} == 'tr__ trist__ tigr__ tigraban en un tigral')
def cadena = ''
10.times {
cadena += 'g'
}
assert cadena == 'gggggggggg'
cadena = ''
1.upto(5) { numero ->
cadena += numero
}
assert cadena == '12345'
cadena = ''
2.downto(-2) { numero ->
cadena += numero + ' '
}
assert cadena == '2 1 0 -1 -2 '
cadena = ''
0.step(0.5, 0.1) { numero ->
cadena += numero + ' '
}
assert cadena == '0 0.1 0.2 0.3 0.4 '
//Rangos inclusivos
assert (0..10).contains(5)
assert (0..10).contains(10)
//Rangos medio-exclusivos
assert (0..<10).contains(9)
assert (0..<10).contains(10) == false
//Comprobación de tipos
def a = 0..10
assert a instanceof Range
//Definición explícita
a = new IntRange(0,10)
assert a.contains(4)
//Rangos para fechas
def hoy = new Date()
def ayer = hoy - 1
assert (ayer..hoy).size() == 2
//Rangos para caracteres
assert ('a'..'f').contains('e')
//El bucle for con rangos
def salida = ''
for (elemento in 1..5){
salida += elemento
}
assert salida == '12345'
//El bucle for con rangos inversos
salida = ''
for (elemento in 5..1){
salida += elemento
}
assert salida == '54321'
//Simulación del bucle for con rangos inversos
//y el método each con un closure
salida = ''
(5..<1).each { elemento ->
salida += elemento
}
assert salida == '5432'
//Rangos como clasificador de grupos
edad = 31
switch (edad){
case 16..20: interesAplicado = 0.25; break
case 21..50: interesAplicado = 0.30; break
case 51..65: interesAplicado = 0.35; break
}
assert interesAplicado == 0.30
//Rangos para el filtrado de datos
edades = [16,29,34,42,55]
joven = 16..30
assert edades.grep(joven) == [16,29]
miLista = [1,2,3]
assert miLista.size() == 3
assert miLista[2] == 3
assert miLista instanceof ArrayList
listaVacia = []
assert listaVacia.size() == 0
listaLarga = (0..1000).toList()
assert listaLarga[324] == 324
listaExplicita = new ArrayList()
listaExplicita.addAll(miLista)
assert listaExplicita.size == 3
listaExplicita[2] = 4
assert listaExplicita[2] == 4
listaExplicita = new LinkedList(miLista)
assert listaExplicita.size == 3
listaExplicita[2] = 4
assert listaExplicita[2] == 4
miLista = ['a','b','c','d','e','f']
assert miLista[0..2] == ['a','b','c']//Acceso con Rangos
assert miLista[0,2,4] == ['a','c','e']//Acceso con colección de índices
//Modificar elementos
miLista[0..2] = ['x','y','z']
assert miLista == ['x','y','z','d','e','f']
//Eliminar elementos de la lista
miLista[3..5] = []
assert miLista == ['x','y','z']
//Añadir elementos a la lista
miLista[1..1] = ['y','1','2']
assert miLista == ['x','y','1','2','z']
miLista = []
//Añado objetos a la lista con el operador +
miLista += 'a'
assert miLista == ['a']
//Añado colecciones a la lista con el operador +
miLista += ['b','c']
assert miLista == ['a','b','c']
miLista = []
miLista << 'a' << 'b'
assert miLista == ['a','b']
assert miLista - ['b'] == ['a']
assert miLista * 2 == ['a','b','a','b']
miLista = ['a','b','c']
//Listas como clasificador de grupos
letra = 'a'
switch (letra){
case miLista: assert true; break;
default: assert false
}
//Listas como filtrado de datos
assert ['x','y','a'].grep(miLista) == ['a']
//Bucle for con lista
salida = ''
for (i in miLista){
salida += i
}
assert salida == 'abc'
def miMapa = [a:1, b:2, c:3]
assert miMapa instanceof HashMap
assert miMapa.size() == 3
assert miMapa['a'] == 1
//Definimos un mapa vacio
def mapaVacio = [:]
assert mapaVacio.size() == 0
//Definimos un mapa de la clase TreeMap
def mapaExplicito = new TreeMap()
mapaExplicito.putAll(miMapa)
assert mapaExplicito['c'] == 3
def miMapa = [a:1, b:2, c:3]
//Varias formas de obtener los valores de un mapa
assert miMapa['a'] == 1
assert miMapa.a == 1
assert miMapa.get('a') == 1
//Si no existe la clave, devuelve un valor por defecto, en este caso 0
assert miMapa.get('a',0) == 1
//Asignación de valores
miMapa['d'] = 4
assert miMapa.d == 4
miMapa.e = 5
assert miMapa.e == 5
def miMapa = [a:1, b:2, c:3]
def resultado = ''
miMapa.each { item ->
resultado += item.key + ':'
resultado += item.value + ', '
}
assert resultado == 'a:1, b:2, c:3, '
resultado = ''
miMapa.each { key, value ->
resultado += key + ':'
resultado += value + ', '
}
assert resultado == 'a:1, b:2, c:3, '
resultado = ''
for (key in miMapa.keySet()){
resultado += key + ':'
resultado += miMapa[key] + ', '
}
assert resultado == 'a:1, b:2, c:3, '
resultado = ''
for (value in miMapa.values()){
resultado += value + ' '
}
assert resultado == '1 2 3 '
def valor1 = [1, 2, 3].every { it < 5 }
assert valor1
def valor2 = [1, 2, 3].any { it > 2 }
assert valor2
def miMapa = [a:1, b:2, c:3]
def miSubmapa = miMapa.subMap(['a','b'])
assert miSubmapa.size() == 2
def miOtromapa = miMapa.findAll { entry -> entry.value > 1 }
assert miOtromapa.size() == 2
assert miOtromapa.c == 3
def encontrado = miMapa.find { entry -> entry.value < 3}
assert encontrado.key == 'a'
assert encontrado.value == 1
def miMapaDoble = miMapa.collect { entry -> entry.value *= 2}
//Todos los elementos son pares
assert miMapaDoble.every { item -> item % 2 == 0 }