Transcript PowerPoint

Opintojakso TT00AA11
Ohjelmoinnin jatko (Java): 3 op
Tietorakenneluokkia 2: HashMap, TreeMap
Tietorakenneluokkia ja -rajapintoja
«interface»Collection
«interface»Map
«interface»
Set
«interface»
List
HashMap
ArrayList
«interface»
SortedMap
TreeMap
 Java tarjoaa laajan kokoelman tietorakennerajapintoja ja luokkia.
 Aiemmin tutustuttiin ArrayList-luokkaan.
 Collection-rajapinnan toteuttajat ovat tietorakenteita
olioille.
 Map-rajapinnan toteuttajat ovat tietorakenteita avain/arvopareille.
20.9.2012
Vesa Ollikainen & Outi Grotenfelt
2
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.
20.9.2012
Vesa Ollikainen & Outi Grotenfelt
3
Esimerkki
 Esimerkissä on tallennettu puhelinliittymien
liittymänumerot ja liittymien saldot.
 avaimena liittymänumero
 arvona saldo
20.9.2012
Vesa Ollikainen & Outi Grotenfelt
4
Määrittely ja alustus Java-kielessä
Map <avaimen_tyyppi, arvon_tyyppi> rakenteen_nimi =
new HashMap <avaimen_tyyppi, arvon_tyyppi>();
 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 Maprajapinnan ilmentymänä.
 Toteuttava luokka voidaan tällöin vaihtaa helposti.
20.9.2012
Vesa Ollikainen & Outi Grotenfelt
5
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.
20.9.2012
Vesa Ollikainen & Outi Grotenfelt
6
Map-rakenteen iterointi
for (Map.Entry<avaimen_tyyppi, arvon_tyyppi>
alkion_nimi : rakenteen_nimi.entrySet()) {
// …
}
 Iterointi onnistuu for/each-rakenteella (yllä).
 Map-rajapinnan metodi entrySet() palauttaa Setrajapinnan edustajan, jonka alkiot ovat Map.Entryrajapinnan 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
20.9.2012
Vesa Ollikainen & Outi Grotenfelt
7
import java.util.*;
public class Puhelinliittymat {
Esimerkki
public static void main(String[] args) {
Map<String, Double> liittymat = new HashMap<String, Double>();
liittymat.put("040-1234567",
liittymat.put("041-8800262",
liittymat.put("043-4837263",
liittymat.put("044-3472897",
102.40); // autoboxing double -> Double
17.15);
0.00);
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.15
null
Liittymän 044-3472897 saldo on 219.36
Liittymän 043-4837263 saldo on 0.0
Liittymän 040-1234567 saldo on 102.4
Liittymän 041-8800262 saldo on 17.15
BUILD SUCCESSFUL (total time: 1 second)
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.
20.9.2012
Vesa Ollikainen & Outi Grotenfelt
8
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 TreeMaprakenteeksi (ja kääntäen) muuttamalla luotavan
rakenteen todellinen tyyppi yhdessä lauseessa:
20.9.2012
Vesa Ollikainen & Outi Grotenfelt
9
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());
}
}
Iteratorrajapinta
}
 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 Iteratoriterointirajapinnan edustajan.
 Iterator-rajapinta sisältää mm. metodit :
 boolean hasNext()
 alkion_tyyppi next()
Täsmälleen sama
tulostus kuin sivulla 8
20.9.2012
Vesa Ollikainen & Outi Grotenfelt
10
Esimerkki
 Luodaan videovuokraamolle tietorakenne, jossa
videovuokraamossa pidetään kirjaa
 elokuvista
 niiden tallenteista
 Videovuokraamo tuntee tallenteensa.
 Tallennetaan ne HashMap-rakenteeseen.
 Saavutetaan nopea haku tallennenumeron
perusteella.
20.9.2012
Vesa Ollikainen & Outi Grotenfelt
11
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;
}
}
20.9.2012
Vesa Ollikainen & Outi Grotenfelt
12
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();
}
}
20.9.2012
Vesa Ollikainen & Outi Grotenfelt
13
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);
}
run:
}
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);
Esimerkki:
Luokka
Videovuokraamo
12648 James Bond 5 213002 Transformers 5
1836 Transformers 5
13003 Transformers 5
13000 Transformers 5
13001 Transformers 5
12649 James Bond 5 2
12648 James Bond 5 2BUILD SUCCESSFUL
(total time: 1 second)
// 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();
}
}
20.9.2012
Vesa Ollikainen & Outi Grotenfelt
14
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/MetropoliaAMK
[email protected]