![]() |
Pràctica 1: Més agrupaments de dades ![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
En el mòdul anterior has pogut descobrir algunes de les capacitats d'agrupament de Java. Les matrius i els vectors et dónen una bona idea de la flexibilitat amb què pots emmagatzemar i cridar ordenadament la informació. Estrictament parlant, les matrius i els vectors et permetran enfrontar gairebé qualsevol situació en la que sigui necessari crear col·lecciones de dades. Tanmateix el Java disposa d'algunes eines més que poden ser una solució adequada al problema de l'agrupament d'objectes. En aquesta pràctica te'n presentem dues:
Amb això no esgotem les capacitats d'agregació de Java. Et deixem com a exercici d'ampliació que descobreixis les classes que implementen els quatre tipus d'agrupament de dades: Collection, Set, List i Map. |
|||||
Inventariar una
botiga de motos |
|||||
Estudiaràs els objectes ArrayList i HashMap amb una aplicació d'inventari de motos que implementi aquestes funcions bàsiques:
Primer estudiaràs com pots fer un programa així amb objectes ArrayList. Quan tinguis clares les capacitats d'aquesta classe, revisaràs el codi del programa i el faràs treballar amb objectes HashTable. Obre el |
|||||
|
|||||
De moment només fem un parell de declaracions i creem un constructor per a la classe on s'instancia un objecte de la classe ArrayList amb el nom inventari. Observa la part superior del programa. Apareix una sentència d'importació. Les importacions les explicarem en aquest mòdul amb una mica de detall. La idea general és que la classe ArrayList està al paquet java.util. Per a poder utilitzar-la al nostre programa hem de dir al compil·lador on pot trobar-la. Aquesta és la raó de fer l'import sobre java.util.ArrayList. |
|||||
private static | |||||
Com sempre, després de la sentència de declaració de la classe, especifiquem els seus camps. Recorda que, preferentment, els camps comencen amb private perquè no siguin directament visibles des de l'exterior de la classe. Observà, però, aquest camp
Ens servirà per a pintar una barra que emmarqui les sortides amb System.out.println() i fer-les més agradables a la vista. Té dues peculiaritats:
Ho hem escrit així per què el camp BARRA tindrà sempre el mateix valor en tots els objectes de la classe GasGas. Quan es crea un objecte d'aquesta classe el valor del camp BARRA es comparteix entre tots els objectes de la classe, és unic per a tothom. En altres llenguatges aquests tipus de camps són coneguts com a Constants. Què creus que passaria si un usuari pogués modificar el valor del camp static BARRA? Pots experimetar-ho si vols.
Com que no ens fa gràcia que un objecte concret de la classe canvïi el contingut de camps estàtics, habitualment no deixarem que els usuaris disposin de mètodes transformadors sobre aquests tipus de camps. Si ho vols assegurar completament, encara pots fer que el valor que assignes a BARRA quan el declares no pugui ser modificat en cap circumstància, ni en el propi codi de la classe. Declara el camp així:
i el valor de BARRA ja no es pot modificar mai des d'enlloc. |
|||||
La feina de l'ArrayList | |||||
De totes les coses que pot fer un ArrayList,
aprofitaràs els mètodes add(),
size(), get() i remove().
Amb això en tens prou per a fer-te una idea de la funcionalitat
de l'objecte i també de les seves limitacions. |
|||||
![]() |
Afegeix, com sempre
per sota d'on has escrit els constructors, el mètode següent: |
||||
public void afegeixMoto(String model) { |
|||||
Aquest mètode permet anar afegint objectes a la llista. En el nostre cas afegim cadenes (String) però podríem posar qualsevol tipus d'objecte -però no tipus primitius-. Convé que sàpigues que l'ArrayList funciona com una cua de cinema (si no es cola ningú): L'objecte que arriba es posa al final de la cua. Si el teu objecte inventari té aquests dos valors: Objecte 0 = "HONDA CBR1000RR FIREBLADE" i afegeixo una tercera moto, la llista em queda així: Objecte 0 = "HONDA CBR1000RR FIREBLADE" Escriu ara els mètodes següents: |
|||||
public
int numeroMotos() { return inventari.size(); } public void eliminaMoto(int moto) { if ((moto>0) || (moto < numeroMotos())) { inventari.remove(moto); } else { System.out.println(BARRA); System.out.println("Aquesta moto no existeix"); System.out.println(BARRA); } } |
|||||
Com pots observar, l'ArrayList no és la millor elecció per a desar grups d'objectes on sigui crític localitzar elements individuals, però si és una bona opció si hem de recórrer la llista sencera d'una punta a l'altra. Finalment, afegirem al programa la capacitat de llistar l'inventari. Escriu aquest nou mètode: |
|||||
public
void llistaMotos() { System.out.println(BARRA); System.out.println("Inventari de GAS / GAS Motor"); System.out.println(BARRA); for (int n=0;n<inventari.size();n++) { System.out.println(BARRA); System.out.println(inventari.get(n)); } } |
|||||
Per a generar la llista sumem dues de les capacitats de l'ArrayList:
|
|||||
Bucles for i bucles while | |||||
Per a recórrer la llista des del primer element a darrer has utilitzat una sentència for. Com ja saps, aquesta estructra va iterant les accions indicades en el cos del bucle mentre es compleixi una condició definida a la capçalera del bucle. En el teu cas, el for es pot traduir en pseudocodi així:
|
|||||
![]() |
|
||||
Podries aconseguir el mateix efecte utilitzant una altra estructura: un bucle while. Prova de substituir el bucle for per aquest codi: |
|||||
int
n=0; while (n<inventari.size()) { System.out.println(BARRA); System.out.println(inventari.get(n)); n++; } |
|||||
El mètode llistaMotos() et funcionarà exactament igual. En qualsevol cas, el que has de vigilar sempre quan recorres una llista, ja sigui un ArrayList o una matriu, és a no sortir fóra del límit de la llista. Sinó, obtindràs un dels errors preferits de java: et saltarà una excepció del tipus IndexOutOfBoundsException.
Si volem publicar tots els elements de la llista sense por a equivocar-nos,
en lloc d'un bucle podem utilitzar un objecte: un iterador. |
|||||
Iteradors | |||||
Els objectes de tipus llista (ArrayList) estan pensats per emmagatzemar grups d'objectes als qui, en algun moment o altre, se'ls "passarà llista", de la mateixa manera que un professor passa llista a classe. Per a facilitar aquesta tasca, Java disposa d'uns objectes especials que només serveixen per a fer fàcil aquesta tasca. Són els iteradors. Tots els objectes de llista estan preparats per treballar conjuntament amb iteradors, que són objectes que s'encarreguen de prendre els valors de la llista i passar-los a qui els necessiti. Per a utilitzar un iterador hem de:
Tot plegat és una mica més senzill i segur que utilitzant només bucles. Prova-ho: Afegeix al programa la sentència següent d'importació: |
|||||
import java.util.Iterator; | |||||
Substitueix el bucle for o while per aquest codi: | |||||
Iterator
iterador = inventari.iterator(); while (iterador.hasNext()) System.out.println(iterador.next()); |
|||||
Procura no oblidar els iteradors. Potser ara et poden semblar una mica rebuscats si estàs acostumat a treballar amb bucles, però són una eficient eina per al tractament de les coleccions en Java. |
|||||
Què pot i no pot fer un ArrayList | |||||
En resum, el nostre programa d'inventari de motos té les principals característiques dels ArrayList:
No està mal. Està clar, però, que aquest tipus de llista no ens soluciona una de les necessitats més importants quan agrupem objectes: la necessitat de localitzar objectes individuals de la llista a partir d'una clau, ja sigui un nom, un codi d'inventari o qualsevol altra cosa. Per a atendre aquestes necessitats, Java disposa
d'altres tipus d'objectes. En aquesta pràctica n'estudiaràs
les HashMap. |
|||||
Les HashMap | |||||
![]() |
Escriuràs una nova versió del projecte motos. Crea una nova classe en el projecte motos amb el nom de GasHash: |
||||
import java.util.Collection; |
|||||
Crea una instància de la classe i afegeix algun element a la llista amb el mètode afegeixMoto(). Has d'entrar dues cadenes per moto: primer la clau i després la descripció de la màquina.
Observa com els mètodes d'entrada i sortida de dades del HashMap són get() i put(). A diferència de l'ArrayList, quan fem una crida al mètode get(), no estem demanant l'objecte que ocupa la posició n a la llista d'objectes, sinó que estem buscant l'objecte la clau del qual sigui n. Aquesta diferència és fonamental entre un tipus d'objecte d'agrupament i l'altre i el que t'ha de fer decidir, en cada situació de programació, quina aproximació has de triar: si només has de llistar objectes consecutius, un ArrayList va molt bé, si has de buscar dins una llista d'objectes a partir d'un camp clau, has de crear un objecte HashMap. |
|||||
![]() |
|
||||
Una altra peculiaritat de la classe que acabes d'escriure està en el mètode llistaMotos(). Recorda que es tracta de la utilitat que ens fa la impressió de tots els elements de la llista. Això, que és evident i transparent en un ArrayList, no és directe en un HashMap (perquè no és un tipus d'objecte pensat per a llistar). Els objectes HashMap no poden passar directament els seus valors a un iterador. Hem de fer una mica de trampa: passarem primer del HashMap a una colecció genèrica i d'aquesta a un iterador. Es fa així: |
|||||