opintojakso tt00aa11 ohjelmoinnin jatko (java): 3 op
DESCRIPTION
Opintojakso TT00AA11 Ohjelmoinnin jatko (Java): 3 op. Tietorakenneluokkia 2: HashMap , TreeMap. Tietorakenneluokkia ja -rajapintoja. Java tarjoaa laajan kokoelman tietorakennerajapintoja ja -luokkia. Aiemmin tutustuttiin ArrayList -luokkaan . - PowerPoint PPT PresentationTRANSCRIPT
Opintojakso TT00AA11 Ohjelmoinnin jatko (Java): 3 op
Tietorakenneluokkia 2: HashMap, TreeMap
Tietorakenneluokkia ja -rajapintoja
Java tarjoaa laajan kokoelman tietorakennerajapintoja ja -luokkia. Aiemmin tutustuttiin ArrayList-luokkaan.
Collection-rajapinnan toteuttajat ovat tietorakenteita olioille. Map-rajapinnan toteuttajat ovat tietorakenteita avain-/arvopareille.
Vesa Ollikainen & Outi Grotenfelt 220.9.2012
«interface»Collection
«interface»Set
«interface»List
ArrayList
«interface»Map
«interface»SortedMapHashMap
TreeMap
Assosiatiivinen taulukko
Assosiatiivisella taulukolla (hajautustaululla) tarkoitetaan tietorakennetta, jossa tieto koostuu avain-arvopareista tieto haetaan avaimen arvon perusteella
Tieto voidaan hakea nopeasti avaimen arvon perusteella. avaimen arvosta lasketaan ns. hajautusarvo, jonka perusteella
tieto löytyy oikeasta muistipaikasta nopeasti. vrt. tavallinen (indeksoitu) taulukko, jossa tieto löytyy nopeasti
indeksin arvon perusteella.
Vesa Ollikainen & Outi Grotenfelt 320.9.2012
Esimerkki
Esimerkissä on tallennettu puhelinliittymien liittymänumerot ja liittymien saldot. avaimena liittymänumero arvona saldo
Vesa Ollikainen & Outi Grotenfelt 420.9.2012
Määrittely ja alustus Java-kielessä
Java-kielessä on HashMap-luokka, joka toteuttaa hajautustaulurakenteen. Alkiot tallennetaan satunnaisessa järjestyksessä.
HashMap-luokka toteuttaa Map-rajapinnan, joka on tarkoitettu avain-arvoparien tallentamiseen.
Versiosta JDK 5.0 alkaen Java-kielessä oleva geneerisyys vaatii määrittämään avainten ja arvojen tyypit luontivaiheessa.
Luotavaa HashMap-oliota suositellaan käsiteltäväksi Map-rajapinnan ilmentymänä. Toteuttava luokka voidaan tällöin vaihtaa helposti.
Vesa Ollikainen & Outi Grotenfelt 520.9.2012
Map <avaimen_tyyppi, arvon_tyyppi> rakenteen_nimi = new HashMap <avaimen_tyyppi, arvon_tyyppi>();
Map-rajapinnan metodeja arvon_tyyppi get(Object avain)
palauttaa avainta vastaavan arvo-olion.
boolean containsKey(Object avain) palauttaa tiedon, esiintyykö avain avainten joukossa
boolean containsValue(Object arvo) palauttaa tiedon, esiintyykö arvo arvojen joukossa.
arvon_tyyppi remove(Object avain) poistaa avaimen määräämän avain-arvoparin.
void clear() tyhjentää hajautustaulukon.
Vesa Ollikainen & Outi Grotenfelt 620.9.2012
Map-rakenteen iterointi
Iterointi onnistuu for/each-rakenteella (yllä). Map-rajapinnan metodi entrySet() palauttaa Set-
rajapinnan edustajan, jonka alkiot ovat Map.Entry-rajapinnan mukaisia avain-arvo pareja. Set-rajapinta on iteroitavissa for/each-rakenteella.
Map.Entry-rajapinta määrittelee metodit avaimen_tyyppi getKey()
palauttaa avaimen arvon_tyyppi getValue()
palauttaa arvon
Vesa Ollikainen & Outi Grotenfelt 720.9.2012
for (Map.Entry<avaimen_tyyppi, arvon_tyyppi> alkion_nimi : rakenteen_nimi.entrySet()) {
// …}
Esimerkki
Esimerkissä tallennetaan neljän puhelinliittymän saldotiedot, haetaan kaksi arvoa avaimen perusteella ja iteroidaan avaimet ja arvot.
Huomaa toistuva autoboxing/autounboxing -ominaisuuden soveltaminen. muunnos alkeistietotyypistä kääreluokan edustajaksi ja toisin päin.
Vesa Ollikainen & Outi Grotenfelt 820.9.2012
import java.util.*;public class Puhelinliittymat {
public static void main(String[] args) { Map<String, Double> liittymat = new HashMap<String, Double>(); liittymat.put("040-1234567", 102.40); // autoboxing double -> Double liittymat.put("041-8800262", 17.15); liittymat.put("043-4837263", 0.00); liittymat.put("044-3472897", 219.36); System.out.println(liittymat.get("041-8800262")); System.out.println(liittymat.get("020-1001001")); for (Map.Entry<String, Double> liittyma: liittymat.entrySet()){ System.out.println("Liittymän "+liittyma.getKey()+" saldo on "+ liittyma.getValue()); } }}
run:17.15nullLiittymän 044-3472897 saldo on 219.36Liittymän 043-4837263 saldo on 0.0Liittymän 040-1234567 saldo on 102.4Liittymän 041-8800262 saldo on 17.15BUILD SUCCESSFUL (total time: 1 second)
TreeMap
TreeMap-tietorakenne tallentaa alkiot avainarvojen mukaisessa järjestyksessä.
Rakenne on käytännössä hitaampi kuin HashMap. Jos hajautusraketta käsitellään Map-rajapinnan
edustajana, voidaan HashMap vaihtaa TreeMap-rakenteeksi (ja kääntäen) muuttamalla luotavan rakenteen todellinen tyyppi yhdessä lauseessa:
Vesa Ollikainen & Outi Grotenfelt 920.9.2012
Iterator-rajapinta
Edellä todettiin, että Set-rajapinta on iteroitavissa. For/each-rakenne on yksinkertaisempi ratkaisu iterointiin. Set-rajapinta toteuttaa myös Collection-rajapinnan vaatiman iterator()-metodin, joka palauttaa Iterator-iterointirajapinnan edustajan.
Iterator-rajapinta sisältää mm. metodit: boolean hasNext() alkion_tyyppi next()
Vesa Ollikainen & Outi Grotenfelt 1020.9.2012
import java.util.*;public class Puhelinliittymat {
public static void main(String[] args) { …. Iterator<Map.Entry<String, Double>> i=liittymat.entrySet().iterator(); while (i.hasNext()){ Map.Entry<String, Double> liittyma = i.next(); System.out.println("Liittymän "+liittyma.getKey()+" saldo on "+ liittyma.getValue()); } }}
Täsmälleen sama tulostus kuin sivulla 8
Esimerkki
Luodaan videovuokraamolle tietorakenne, jossa videovuokraamossa pidetään kirjaa elokuvista niiden tallenteista
Videovuokraamo tuntee tallenteensa. Tallennetaan ne HashMap-rakenteeseen. Saavutetaan nopea haku tallennenumeron
perusteella.
Vesa Ollikainen & Outi Grotenfelt 1120.9.2012
Vesa Ollikainen & Outi Grotenfelt 1220.9.2012
Esimerkki: Luokka Leffa
public class Leffa { private String nimi; private int hinta; public Leffa(String nimi, int hinta){ this.nimi = nimi; this.hinta = hinta; } public String toString(){ return nimi + " " + hinta; }}
Vesa Ollikainen & Outi Grotenfelt 1320.9.2012
Esimerkki: Luokka Tallenne
public class Tallenne { private int tallenneKoodi; private Leffa elokuva; public Tallenne(int tallenneKoodi, Leffa elokuva){ this.tallenneKoodi = tallenneKoodi; this.elokuva = elokuva; } public String toString(){ return tallenneKoodi + " " + elokuva.toString(); }}
Vesa Ollikainen & Outi Grotenfelt 1420.9.2012
import java.util.*;
public class Videovuokraamo { private Leffa movie1, movie2; private Map<Integer, Tallenne> dvdt = new HashMap<Integer, Tallenne>();
private void rekisteroi(Leffa movie, int lkm, int ekakoodi){ for (int i=ekakoodi; i<ekakoodi+lkm; i++){ Tallenne dvd = new Tallenne(i, movie); dvdt.put(new Integer(i), dvd); } }
private void operoi(){ movie1 = new Leffa("James Bond 5", 2); movie2 = new Leffa("Transformers", 5);
rekisteroi(movie1, 2, 12648); rekisteroi(movie2, 1, 1836); rekisteroi(movie2, 4, 13000);
// hae tallenne 12648 System.out.print(dvdt.get(12648));
// hae kaikki tallenteet for (Map.Entry<Integer, Tallenne>dvd : dvdt.entrySet()){ System.out.println(dvd.getValue()); } }
public static void main(String[] args){ Videovuokraamo munMaku = new Videovuokraamo(); munMaku.operoi(); }}
Esimerkki: Luokka Videovuokraamo
run:12648 James Bond 5 213002 Transformers 51836 Transformers 513003 Transformers 513000 Transformers 513001 Transformers 512649 James Bond 5 212648 James Bond 5 2BUILD SUCCESSFUL (total time: 1 second)
Uutta ja vanhaa Javaa
Ennen JDK 5.0 -versiota tietorakenneluokkien käsittely oli hankalampaa: Ei geneerisyyttä. Rakenteisiin voitiin tallentaa mitä tahansa olioita. Tyypinmuunnoksista oli huolehdittava itse.
Ei automaattista käärimistä alkeistyypeille ja takaisin (autoboxing/autounboxing).
Ei for/each-rakennetta. Luotava Iterator-rajapinnan ilmentymä.
Kalvosarjan tekijän nimi 15
THANK YOU!
www.metropolia.fi/en/www.facebook.com/[email protected]