Google Guava?

Google GuavaIl Progetto Guava contiene molte delle core libraries usate da Google nei progetti Java-based. Queste librerie coprono molti aspetti: le collection, la cache, la gestione della concorrenza, il processamento delle stringhe, l’I/O e così via.

Un’altra libreria?

Sicuramente di librerie ben progettate che semplificano molto il lavoro dello sviluppatore Java ce ne sono parecchie: tra tutte cito soltanto il set di librerie Apache Commons, usatissime e preziose. Inoltre c’è da dire che anche il linguaggio Java standard sta evolvendo: Java7 e Java8 prevedono diverse modifiche al linguaggio, che sta diventando più potente ma allo stesso tempo più stringato, seguendo la tendenza di altri linguaggi, uno fra tutti: Scala.

Nonostante questo non si può non dedicare un piccolo post ad una libreria Java che, beh, è fatta da Google (e usata dal progetto JBoss RichFaces4, tra gli altri)! Siete pronti? Andiamo!

Partenza!

Sono partito dal mio fido Eclipse: è possibile scaricarsi il Jar guava-11.0.1.jar e aggiungerlo al build path oppure utilizzare Maven inserendo la seguente dipendenza nel nostro pom.xml:

<dependencies>
  	<dependency>
  		<groupId>com.google.guava</groupId>
  		<artifactId>guava</artifactId>
  		<version>11.0.1</version>
  	</dependency>
  </dependencies>

Ulteriori dettagli sono disponibili nella documentazione di Google (Use Guava In Your Build).

Guava, come lava!

Crea collection in modo rapido

Le collection generiche sono una grande introduzione di Java 5, ma la loro creazione può essere davvero un po’ troppo verbosa:

Map<String, Map<String, Integer>> mappa = new HashMap<String, Map<String, Integer>>();

Con Guava la precedente inizializzazione diventa molto più succinta:

Map<String, Map<String, Integer>> mappa = Maps.newHashMap();

Un tocco di functional

Come filtrare ad esempio gli elementi di una lista in modo che rimangano solo quelli != null? Alle ortiche il vecchio ciclare, direbbero i funzionali: e anche in Guava abbiamo un comodo metodo filter:

public class MainTest {
	private static List<Integer> integers;

	@BeforeClass
	public static void init() {
		integers = new ArrayList<Integer>();
		integers.add(1);
		integers.add(null);
		integers.add(3);
		integers.add(null);
		integers.add(5);
	}

	@Test
	public void testFilter() {
		Collection<Integer> filtered = Collections2.filter(integers,
				Predicates.notNull());

		assertEquals(3, filtered.size());
		
		Collection<Integer> filtered2 = Collections2.filter(integers, Predicates.or(Predicates.equalTo(1), Predicates.equalTo(3)));
		
		assertEquals(2, filtered2.size());
	}
}

Da notare che filter non modifica la collezione passata in ingresso, ma ne restituisce una copia diversa. Per modificare la collezione originaria si può utilizzare il metodo trasform.

MultiMaps

Non di rado utilizziamo una Map per memorizzare valori multipli in corrispondenza della stessa chiave. L’utilizzo di Java standard implica scrivere codice verboso in questi casi, ma utilizzando le Multimaps di Guava il codice diventa minimalista:

Multimap<String, Integer> punteggi = HashMultimap.create();
punteggi.put("Manuele", 20);
punteggi.put("Manuele", 10);
punteggi.put("Manuele", 15);
System.out.println(Collections.max(punteggi.get("Manuele"))); 
// scrive 20 in console

HashCode, toString e compareTo

Quasi sicuramente ci si trova a definire l’hashCode (e l’equals in modo coerente) nei nostri Pojo, così come il toString, tanto comodo tra l’altro per il logging e il debugging.

Per quanto riguarda l’hashCode di solito si fa generare ad Eclipse (Menu Source -> Generate hashCode() and equals…), ma il codice prodotto tuttavia risulta sempre un po’ ostico e verboso. Se vogliamo del codice più pulito possiamo utilizzare un metodo di utilità della classe Objects:

public class Persona
{
   private String nome;
   private String cognome;
   ...
   @Override
   public int hashCode() {
	return Objects.hashCode(nome, cognome);
   }
}

Veniamo al toString: ne volete uno elegante scrivendo poco codice? Allora usate il metodo Objects.toStringHelper:

public class Persona
{ 
@Override
   public String toString() {
	return Objects.toStringHelper(this).add("nome", nome).add("cognome", cognome).toString();
   }
@Test
	public void testToString() {
		Persona persona = new Persona("Manuele", "Piastra");
		System.out.println(persona);
		//Scrive Persona{nome=Manuele, cognome=Piastra}
	}

Anche il metodo compareTo dell’interfaccia Comparable si implementa in modo più smart grazie alla classe ComparisonChain:

public class Persona implements Comparable<Persona> {
{
   private String nome;
   private String cognome;
   ...
  @Override
	public int compareTo(Persona p) {
		return ComparisonChain.start().compare(this.nome, p.nome).compare(this.cognome, p.cognome).result();
	}
}

Occhio alla precondizioni

Se ci si trova spesso a testare certe precondizioni Guava può darci una mano facendoci scrivere meno codice più leggibile; ad esempio anziché scrivere:

if (eta <= 18) {
    throw new IllegalArgumentException("Hai " + eta + " anni: devi essere maggiorenne per guidare!");
}

possiamo utilizzare:

Preconditions.checkArgument(eta > 18, "Hai %s anni: devi essere maggiorenne per guidare!", eta);

ottenendo lo stesso identico risultato.

Conclusioni

Volete scrivere del codice più smart e non potete passare a Java7? Allora le Apache Commons e le Google Guava sono due ottime alternative. Sicuramente ciascuna delle due ha pregi e difetti e credo che solo usandole per un po’ si riesca a capire quale abbia il design che preferiamo. Una cosa è sicura: entrambe sono librerie di qualità che possono migliorare la nostra produttività e rendere il nostro codice più stringato e manutenibile.

E voi avete usato Guava? Qual’è stata la vostra esperienza a riguardo? Avete qualche altro suggerimento da aggiungere? Alla prossima!

37 Posts

Sono uno Scrum Master e Project Manager i cui skill tecnici sono focalizzati al momento sullo sviluppo di applicazioni Java EE su IBM Websphere 7.0 utilizzando JSF (RichFaces), JPA (EclipseLink) ed EJB3. Presso OmniaGroup ricopro il ruolo di Training Manager: seleziono il personale tecnico, mi occupo della sua crescita formativa organizzando Corsi e Workshop sia interni che esterni, molti dei quali hanno visto me come docente. LinkedIn Profile - Google+