martes, 2 de junio de 2009

Java: lambdaj

Hace unos días, hablando con un amigo, digamos ... Federico, me decía que hace tiempo que no pongo nada en el blog. Y tiene razón, así que aprovechando que he estado jungando con la librería lambdaj, voy a poner las pruebitas que he hecho.

Lambaj emula los lenguajes funcionales, permitiendo tratar colecciones de una forma más sencilla, intentando reducir el número de líneas de código necesarias para operar sobre ellas.

Antes de empezar, comentar que si miramos el código mostrado en los ejemplos que acompañan a la documentación de la librería, vemos que se llaman directamente funciones como asList, forEach, ... Evidentemente, si simplemente copiamos y pegamos este código en nuestro proyecto (tras haber incluido la librería), no compilará. Lo que se ha hecho en el ejemplo es importar de forma estática los métodos estáticos de ciertas clases. Es decir, si lo hacemos de la forma más habitual, tendría que hacer algo como:


import java.util.Arrays;

...

Arrays.asList(...)



Pero si hacemos uso de los static imports, que permiten acceso a los miembros estáticos extendiendo el tipo. Es decir, todos los campos estáticos, métodos, etc. estarán disponibles para nuestra Clase. Por ejemplo, podríamos hacer algo como:


import static java.util.Arrays.asList;

...

asList(...)



Bien, aclarado esto, vamos a ver algunos ejemplos. Para realizar las pruebas, usé la siguiente clase:


package es.gmr.modelo;

public class Coche {

private Integer cilindrada = null;
private Integer anyo = null;
private boolean disponible = false;

// --- Constructor

public Coche(){}

public Coche(Integer cilindrada, Integer anyo) {
this.cilindrada = cilindrada;
this.anyo = anyo;
}

// --- getters && setters

public Integer getCilindrada() {
return cilindrada;
}

public void setCilindrada(Integer cilindrada) {
this.cilindrada = cilindrada;
}

public Integer getAnyo() {
return anyo;
}

public void setAnyo(Integer anyo) {
this.anyo = anyo;
}

public boolean isDisponible() {
return disponible;
}

public void setDisponible(boolean disponible) {
this.disponible = disponible;
}
}


Y ahí va el primer ejemplo: invocar un método sobre todos los objetos de una lista


package es.gmr.pruebas;

import static ch.lambdaj.Lambda.forEach;
import static java.util.Arrays.asList;

import java.util.List;

import es.gmr.modelo.Coche;

public class PruebaLambdaj {

public static void main(String[] args) {
final List listaCoches = asList(new Coche(1600, 2000),
new Coche(1400, 2002), new Coche(2000, 2005));

forEach(listaCoches).setDisponible(true);

for (final Coche coche : listaCoches){
System.out.println("¿Está disponible? " + (coche.isDisponible() ? "SI" : "NO"));
}
}
}


Algo importante a tener en cuenta, que en la documentación no he visto, es que si la clase Coche no tuviera el constructor sin parámetros, tendríamos un error en tiempo de ejecución.

En el segundo ejemplo se filtrará la lista, obteniendo sólo los coches matriculados después del año 2000. La librería trae algunos filtros, pero lo interesante es que podemos implementar nuestros propios filtros, con la librería Hamcrest


package es.gmr.pruebas;

import static ch.lambdaj.Lambda.filter;
import static java.util.Arrays.asList;

import java.util.List;

import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.junit.matchers.TypeSafeMatcher;

import es.gmr.modelo.Coche;

public class PruebaLambdaj {

public static void main(String[] args) {
final List listaCoches = asList(new Coche(1600, 2000),
new Coche(1400, 2002), new Coche(2000, 2005));

final Matcher nuevo = new TypeSafeMatcher() {
@Override
public boolean matchesSafely(Coche item) {
return item.getAnyo() > 2000;
}

public void describeTo(Description description) {
description.appendText("nuevo()");
}
};

final List listaFiltrada = filter(nuevo, listaCoches);

for (final Coche coche : listaFiltrada){
System.out.println("Año matriculación: " + coche.getAnyo());
}
}
}


Por último, vemos dos formas de ordenar la lista, con un Comparator y sin él:


package es.gmr.pruebas;

import static ch.lambdaj.Lambda.on;
import static ch.lambdaj.Lambda.sort;

import static java.util.Arrays.asList;

import java.util.Comparator;

import java.util.List;

import es.gmr.modelo.Coche;

public class PruebaLambdaj {

public static void main(String[] args) {
final List listaCoches = asList(new Coche(1600, 2000),
new Coche(1400, 2002), new Coche(2000, 2005));

final Comparator comparator = new Comparator(){
public int compare(Coche c1, Coche c2) {
return -1 * c1.getCilindrada().compareTo(c2.getCilindrada());
}
};

final List listaOrdenadaA = sort(listaCoches, on(Coche.class).getCilindrada());
final List listaOrdenadaB = sort(listaCoches, on(Coche.class), comparator);

for (final Coche coche : listaOrdenadaA){
System.out.println("Cilindrada: " + coche.getCilindrada());
}

System.out.println("---");

for (final Coche coche : listaOrdenadaB){
System.out.println("Cilindrada: " + coche.getCilindrada());
}
}
}


Hay muchas más opciones... pero para muestra un botón ;)

No hay comentarios:

Publicar un comentario