Programmare con JCF Descrizione del problema Consideriamo il problema di progettare la struttura di un indice analitico per un libro. L’indice analitico e’ costituito da un elenco dei termini che compaiono nel libro. Accanto a ogni termine e’ presente la lista delle pagine in cui appare tale termine. Per progettare l’indice abbiamo pertanto bisogno di una struttura dati che può contenere un elenco di termini, insieme a una lista di pagine per ogni termine. Obiettivo: progettare la struttura indice utilizzando JCF. Possiamo progettare la nostra struttura dati indice come una istanza della struttura Map che associa a un termine la lista delle pagine del libro dove il termine compare. In altre parole, i termini giocano il ruolo della chiave e la lista delle pagine gioca il ruolo dei valori della Map. Andiamo a esaminare la documentazione di JCF. “The Java platform contains three general-purpose Map implementations: HashMap, TreeMap, and LinkedHashMap. Their behavior and performance are precisely analogous to HashSet, TreeSet, and LinkedHashSet, as described in The Set Interface section.” Nel nostro caso la soluzione migliore e’ quella di adottare una rappresentazione che ordini i termini in modo crescente (ordine lessicografico). Ancora una volta esaminando la documentazione scopriamo che TreeMap e’ la scelta opportuna Ora dobbiamo esaminare la progettazione del valore associato alla chiave (la lista delle pagine). Si puo’ facilmente vedere (basta guardare un qualunque indice dei nomi di un libro) che l’elenco delle pagine non contiene valori duplicati quindi e’ sostanzialmente un insieme di pagine piuttosto che una lista di pagine. Inoltre , le pagine sono sono sempre rappresentate in ordine crescente. Pertanto la struttura dati che risolve il nostro problema e’ un insieme ordinato (TreeSet e’ una buona scelta). I valori che vogliamo davvero mettere in questa serie sono di tipo int quindi dobbiamo utilizzare la classe wrapper , Integer. La nostra scelta di progetto pertanto risulta TreeMap< String, TreeSet> La struttura potrebbe a prima vista intimidire chi programma ma in realta’ e’ un semplice elemento della JCF TreeMap dove K=String e V=TreeSet. Programmare un servizio Ora, supponiamo di aver individuato un termine (di tipo String) su alcune pagine del libro pageNum. Queste informazioni devono essere inserite nell’indice che stiamo costruendo. Per fare questo, dobbiamo cercare il termine nell'indice, utilizzando index.get (termine). Il valore restituito dal metodo e’ nullo, oppure e’ l'insieme di riferimenti alle pagine che abbiamo gia’ inserito per quel termine. Se il valore restituito e’ null, allora questo e’ il primo riferimento per il termine, quindi dovremmo aggiungere il termine nell'indice, associando il riferimento alla pagina che abbiamo appena trovato. Se il valore di ritorno è diverso da null, abbiamo da aggiungere il nuovo riferimento all’insieme dei riferimenti gia’ presenti. /** * Add a page reference to the index. */ void addReference(String term, int pageNum) { TreeSet references ; // The set of page references . references = index.get(term); if (references == null){ // This is the first reference that we have // found for the term. TreeSet firstRef = new TreeSet(); firstRef.add( pageNum ); // pageNum is "autoboxed" to give an Integer! index.put(term,firstRef); } else { // references is the set of page references references.add( pageNum ); // pageNum is "autoboxed" to give an Integer! } }