Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Apache Commons: Collections

Potenziare la gestione delle collezioni, con funzionalità avanzate e automatismi
Potenziare la gestione delle collezioni, con funzionalità avanzate e automatismi
Link copiato negli appunti

Quante applicazioni di Java non usano liste, array, mappe o qualche altro tipo di collezione? Praticamente nessuna. Le collezioni sono uno strumento prezioso e utilizzato in moltissimi contesi differenti: proprio per questo talvolta le funzionalità offerta dalla libreria standard di Java non bastano. In questo articolo esaminiamo il componente Collections del progetto Apache Commons e tramite una serie di brevi esempi illustriamo alcune fra le molte funzionalità offerte.

Possiamo scaricare la libreria originale Apache Commons Collections, che non fa uso dei generics introdotti in Java 1.5. In alternativa esiste un fork che re-implementa le stesse funzionalità utilizzando questa "nuova" caratteristica del linguaggio. Nel corso dell'articolo faremo riferimento al progetto originario ma tutti gli esempi possono essere facilmente adattati all'utilizzo con il fork di larvalabs.

BidiMap

La libreria contiene una classe chiamata BidiMap che implementa una mappa bidirezionale. Una mappa bidirezionale (biettiva) permette di definire una relazione 1:1 fra gli elementi di due insiemi. Supponiamo ad esempio di avere una lista di uffici ed una lista di persone. Dato un ufficio vorremmo sapere quale persona lo occupa e data una persona in quale ufficio si trovi, utilizzando una BidiMap bastano poche righe di codice.

// Assegnazione uffici a persone
BidiMap officeAssignments = new DualHashBidiMap();
officeAssignments.put(federicoTomassetti, tw001);
officeAssignments.put(paoloRossi, sc751);
officeAssignments.put(andreaBianchi, sc581);
officeAssignments.put(lucaVerdi, sc521);
System.out.println("In quale ufficio si trova "+andreaBianchi+"?");
System.out.println("> "+officeAssignments.get(andreaBianchi));
System.out.println("Chi ha l'ufficio "+tw001+"?");
System.out.println("> "+officeAssignments.getKey(tw001));

PriorityBuffer

Questa classe implementa una collezione per la quale è possibile stabilire delle regole di priorità secondo le quali scegliere gli elementi da rimuovere. Supponiamo ad esempio di avere una collezione di titoli di borsa che rappresenti un portafoglio di investimenti e di volere rimuovere per primi i titoli meno profittevoli, ecco come fare utilizzando un PriorityBuffer:

StockShare carLtd = new StockShare("Car Ltd", 0.12);
StockShare bankInc = new StockShare("Bank inc.", 7.12);
StockShare acme = new StockShare("Acme manufacturing", 9.12);
StockShare giantOil = new StockShare("Giant Oil", -2.12);
PriorityBuffer priorityBuffer = new PriorityBuffer(new StockShareComparator());
priorityBuffer.add(carLtd);
priorityBuffer.add(bankInc);
priorityBuffer.add(acme);
priorityBuffer.add(giantOil);
System.out.println("Elemento rimosso: "+priorityBuffer.remove());

L'esempio fa riferimento alla classe StockShareComparator che gestisce la comparazione di StockShare in base al loro profitto. Il titolo che viene rimosso è GiantOil, l'unico a presentare un profitto negativo.

LRUMap

La LRUMap è una classe utile per rappresentare una collezione di dimensione fissa. Quando si inserisce un nuovo elemento in un'istanza che ne contiene già il numero massimo, viene rimosso l'elemento che non viene utilizzato da più tempo (Least Recently Used).

Supponiamo ad esempio che una software house abbia un insieme di dipendenti e ad un certo punto decida di assumere un addetto ai test e per liberare un posto decida di licenziare il dipendente che da più tempo non viene coinvolto in un progetto. Ecco come si potrebbe rappresentare la soluzione con una LRUMap:

// inserimento
LRUMap lruMap = new LRUMap(3);
lruMap.put(programmer, armandoNeri);
lruMap.put(manager, andreaBianchi);
lruMap.put(analyst, lucaVerdi);
// simulazione di "utilizzo"
lruMap.get(analyst);
lruMap.get(programmer);
lruMap.get(analyst);
lruMap.get(programmer);
lruMap.get(programmer);
lruMap.get(programmer);
lruMap.get(manager);
lruMap.get(programmer);
lruMap.put(tester, paoloRossi);
System.out.println("È stato licenziato il programmatore? "+(!lruMap.containsKey(programmer)));
System.out.println("È stato licenziato l'analista? "+(!lruMap.containsKey(analyst)));
System.out.println("È stato licenziato il manager? "+(!lruMap.containsKey(manager)));

Nel caso proposto viene licenziato l'analista.

CollectionUtils

Oltre ad una serie di collezioni per esigenze specifiche il progetto contiene anche altre classi che raccolgono metodi di utilità generale per manipolare Collection, Set, Map e quant'altro.

Fra queste la più generale è CollectionUtils perchè può essere adoperata su ogni Collection.

Questa classe contiene ad esempio il metodo intersection il quale, date due Collection ne produce una terza contenente gli elementi comuni a quelle fornite. Immaginiamo di avere una Collection contenente i siti che riteniamo interessanti ed una contenente una lista di siti "tecnici". Possiamo ottenere facilmente una Collection contenente i siti sia tecnici che interessanti:

Collection interestingSites = new LinkedList();
interestingSites.add("My-favourite-newspaper.net");
interestingSites.add("ASportMagazine.it");
interestingSites.add("Html.it");
Collection techSites = new LinkedList();
techSites.add("MySuperPcGuide.org");
techSites.add("UltraMac.com");
techSites.add("Html.it");
Collection interestingTechSites = CollectionUtils.intersection(interestingSites, techSites);
System.out.println("Interesting tech sites:");
for (Object site : interestingTechSites) {
  System.out.println("- "+site);
}

Un concetto interessante introdotto da questa libreria è il concetto di Transformer. Un Transformer è un oggetto che, ricevuto un input lo elabora per produrre un risultato. È possibile utilizzando il metodo transformedCollection di CollectionsUtils specificare un Transformer che verrà applicato a tutti gli elementi di una Collection.

L'esempio seguente ad esempio definisce una Collection contenente un URL per ogni elemento della Collection di input:

Collection urls = CollectionUtils.transformedCollection(interestingTechSites, new Transformer() {
  @Override
  public Object transform(Object s) {
    try {
      return new URL((String) s);
    } catch (MalformedURLException e) {
      return new IllegalArgumentException("Bad URL string given: "+s);
    }
  }
});

Conclusioni

In questo articolo abbiamo esaminato alcune delle funzionalità fornita da Apache Commons Collections in modo da rendere percebile la ricchezza di questa libreria. Ricordatevene quando avrete bisogno di una collezione diversa da quelle presenti nella libreria standard; con buona probabilità la troverete fra quelle offerte da questo progetto.

Ti consigliamo anche