(Muutettu viimeksi 30.10.2011, sivu perustettu 25.10.2011.)
Nämä harjoitukset liittyvät lähinnä kurssimateriaalin lukuihin 2-6.
Kaikki harjoitustehtävät on syytä tehdä. Jotkin tehtävät on merkitty keltaisella värillä. Ne ovat ehkä hieman muita haastavampia. Ilman niitäkin harjoituksista voi saada maksimipisteet, mutta ne lasketaan silti mukaan harjoituspisteitä määrättäessä – ne voivat siis korvata joitakin haasteettomampia tehtäviä tms. Mutta ennen kaikkea noista keltaisista tehtävistä sitä vasta oppiikin!
Huom:
// 1. harjoitukset, tehtävä 3.2, Oili Opiskelija
Laadi luentomateriaalin ArrayList-esimerkkiä jäljitellen seuraava palvelu: Aluksi ohjelma kyselee joukon "osallistujien" nimiä standardisyöttövirrasta. Tyhjä merkkijono päättää nimien syötön. Tämän jälkeen ohjelma tarjoaa varsinaisen palvelunsa: Ohjelmalle syötetään nimi ja se tulostaa standarditulosvirtaan joko tiedon, ettei "osallistujaa" löydy tai "osallistujan" nimen ja hänen järjestysnumeronsa eli tiedon siitä, monentenako nimi syötettiin. Tyhjä nimi päättää ohjelman suorituksen.
Suoritusesimerkki (käyttäjän kirjoittamat tekstit tässä kursiivilla):
Anna osallistujan nimi. Tyhjä lopettaa. Jyrki Anna osallistujan nimi. Tyhjä lopettaa. Jutta Anna osallistujan nimi. Tyhjä lopettaa. Stefan Anna osallistujan nimi. Tyhjä lopettaa. Paavo Anna osallistujan nimi. Tyhjä lopettaa. Päivi Anna osallistujan nimi. Tyhjä lopettaa. Heidi Anna osallistujan nimi. Tyhjä lopettaa. Osallistujakysely. Tyhjä lopettaa. Jutta Jutta: 2 Mari Mari puuttuu! Heidi Heidi: 6 Timo Timo puuttuu!
Ohjelman ensiversio sallii saman nimen syöttämisen useampaan kertaan. Korjaa tämä puute. Tarjoa lisäksi kyselyn yhteydessä mahdollisuus lisätä puuttuva "osallistuja" ja poistaa löytynyt "osallistuja".
Suoritusesimerkki (käyttäjän kirjoittamat tekstit tässä kursiivilla):
Anna osallistujan nimi. Tyhjä lopettaa. Jyrki Anna osallistujan nimi. Tyhjä lopettaa. Jutta Anna osallistujan nimi. Tyhjä lopettaa. Stefan Anna osallistujan nimi. Tyhjä lopettaa. Jyrki On jo! Anna osallistujan nimi. Tyhjä lopettaa. Osallistujakysely. Tyhjä lopettaa. Mari Mari puuttuu! Lisätäänkö? (tyhjä = ei, kaikki muut = kyllä) Osallistujakysely. Tyhjä lopettaa. Paavo Paavo puuttuu! Lisätäänkö? (tyhjä = ei, kaikki muut = kyllä) joo Osallistujakysely. Tyhjä lopettaa. Jyrki Jyrki: 1. Poistetaanko? (tyhjä = ei, kaikki muut = kyllä) ok Osallistujakysely. Tyhjä lopettaa. Jutta Jutta: 1. Poistetaanko? (tyhjä = ei, kaikki muut = kyllä) Osallistujakysely. Tyhjä lopettaa.
Tässä tehtäväsarjassa tehdään luokat Tavara
ja Matkalaukku
,
joiden avulla käsitellään matkalaukussa olevia tavaroita.
Oikeastaan kahdessa ensimmäisessä tehtäväsarjassa harjoitellaan ensiksikin sitä, miten luokkamäärittelyn kenttä itse voi olla viittaustyyppinen eli miten "oliossa voi olla olioita". Lisäksi harjoitellaan eritysesti sitä, miten "olio voi sisältää" vieläpä vaihtelevan määrän olioita – "matkalaukussa tavaroita" ja "lastiruumassa matkalaukkuja".
Tee luokka Tavara
, josta muodostetut oliot vastaavat erilaisia tavaroita.
Tallennettavat tiedot ovat tavaran nimi ja paino (kg).
APIn luonnehdinta:
getNimi
palauttaa tavaran nimen
getPaino
palauttaa tavaran painon
toString
palauttaa merkkijonon tyyliin "Aapiskukko (2 kg)"
Käyttöesimerkki:
public class Main { public static void main(String[] args) { Tavara kirja = new Tavara("Aapiskukko", 2); Tavara puhelin = new Tavara("Nokia 3210", 1); System.out.println("Kirjan nimi: " + kirja.getNimi()); System.out.println("Kirjan paino: " + kirja.getPaino()); System.out.println("Kirja: " + kirja); System.out.println("Puhelin: " + puhelin); } }
Ohjelman tulostuksen tulisi olla seuraava:
Kirjan nimi: Aapiskukko Kirjan paino: 2 Kirja: Aapiskukko (2 kg) Puhelin: Nokia 3210 (1 kg)
Tee luokka Matkalaukku
, johon liittyy maksimipaino.
APIn luonnehdinta:
lisaaTavara
lisää tavaran matkalaukkuun
lisaaTavara(Tavara lisattavaTavara)
]
toString
palauttaa merkkijonon tyyliin "2 tavaraa (3 kg)"
Tallenna tavarat seuraavaan ArrayList
-rakenteeseen:
ArrayList<Tavara> tavarat = new ArrayList<Tavara>();
Luokan Matkalaukku
tulee valvoa,
että sen tavaroiden yhteispaino ei ylitä maksimipainoa.
Jos maksimipaino ylittyisi uuden tavaran vuoksi,
metodi lisaaTavara
ei lisää tavaraa matkalaukkuun.
Käyttöesimerkki:
public class Main { public static void main(String[] args) { Tavara kirja = new Tavara("Aapiskukko", 2); Tavara puhelin = new Tavara("Nokia 3210", 1); Tavara tiiliskivi = new Tavara("tiiliskivi", 4); Matkalaukku matkalaukku = new Matkalaukku(5); System.out.println(matkalaukku); matkalaukku.lisaaTavara(kirja); System.out.println(matkalaukku); matkalaukku.lisaaTavara(puhelin); System.out.println(matkalaukku); matkalaukku.lisaaTavara(tiiliskivi); System.out.println(matkalaukku); } }
Ohjelman tulostuksen tulisi olla seuraava:
0 tavaraa (0 kg) 1 tavaraa (2 kg) 2 tavaraa (3 kg) 2 tavaraa (3 kg)
Ilmoitukset "0 tavaraa" ja "1 tavaraa" eivät ole kovin hyvää suomea
– paremmat muodot olisivat "tyhjä" ja "1 tavara".
Tee tämä muutos luokkaan Matkalaukku
.
Nyt edellisen ohjelman tulostuksen tulisi olla seuraava:
tyhjä (0 kg) 1 tavara (2 kg) 2 tavaraa (3 kg) 2 tavaraa (3 kg)
Lisää luokkaan Matkalaukku
seuraavat metodit:
tulostaTavarat
tulostaa kaikki matkalaukussa olevat tavarat
yhteispaino
palauttaa tavaroiden yhteispainon
Käyttöesimerkki:
public class Main { public static void main(String[] args) { Tavara kirja = new Tavara("Aapiskukko", 2); Tavara puhelin = new Tavara("Nokia 3210", 1); Tavara tiiliskivi = new Tavara("tiiliskivi", 4); Matkalaukku matkalaukku = new Matkalaukku(10); matkalaukku.lisaaTavara(kirja); matkalaukku.lisaaTavara(puhelin); matkalaukku.lisaaTavara(tiiliskivi); System.out.println("Matkalaukussa on seuraavat tavarat:"); matkalaukku.tulostaTavarat(); System.out.println("Yhteispaino: " + matkalaukku.yhteispaino() + " kg"); } }
Ohjelman tulostuksen tulisi olla seuraava:
Matkalaukussa on seuraavat tavarat: Aapiskukko (2 kg) Nokia 3210 (1 kg) Tiiliskivi (4 kg) Yhteispaino: 7 kg
Lisää vielä luokkaan Matkalaukku
metodi raskainTavara
,
joka palauttaa painoltaan suurimman tavaran. Jos yhtä raskaita tavaroita on useita,
metodi voi palauttaa minkä tahansa niistä. Metodin palauttaa siis viitteen olioon.
Käyttöesimerkki:
public class Main { public static void main(String[] args) { Tavara kirja = new Tavara("Aapiskukko", 2); Tavara puhelin = new Tavara("Nokia 3210", 1); Tavara tiiliskivi = new Tavara("tiiliskivi", 4); Matkalaukku matkalaukku = new Matkalaukku(10); matkalaukku.lisaaTavara(kirja); matkalaukku.lisaaTavara(puhelin); matkalaukku.lisaaTavara(tiiliskivi); Tavara raskain = matkalaukku.raskainTavara(); System.out.println("Raskain tavara: " + raskain); } }
Ohjelman tulostuksen tulisi olla seuraava:
Raskain tavara: tiiliskivi (4 kg)
Lisää luokkaan Matkalaukku
metodi poimiTavara
,
joka palauttaa matkalaukusta satunnaisen tavaran.
Metodin ei ole tarkoitus poistaa tavaraa matkalaukusta,
vaan ainoastaan palauttaa viite satunnaisesti valittuun Tavara-olioon.
Käyttöesimerkki:
public class Main { public static void main(String[] args) { Tavara kirja = new Tavara("Aapiskukko", 2); Tavara puhelin = new Tavara("Nokia 3210", 1); Tavara tiiliskivi = new Tavara("tiiliskivi", 4); Matkalaukku matkalaukku = new Matkalaukku(10); matkalaukku.lisaaTavara(kirja); matkalaukku.lisaaTavara(puhelin); matkalaukku.lisaaTavara(tiiliskivi); Tavara satunnainen = matkalaukku.poimiTavara(); System.out.println("Satunnainen tavara: " + satunnainen); } }
Ohjelman mahdollisia tulostuksia ovat seuraavat:
Satunnainen tavara: Aapiskukko (2 kg)
Satunnainen tavara: Nokia 3210 (1 kg)
Satunnainen tavara: tiiliskivi (4 kg)
Selitä ohjaajalle miten käsite kapselointi liittyy tehtäväsarjassa 3 toteuttamaasi ratkaisuun.
Tässä tehtäväsarjassa tehdään luokka Lastiruuma
,
joka esittää matkalaukkuja sisältävää lastiruumaa.
Tee luokka Lastiruuma
.
APIn luonnehdinta:
lisaaMatkalaukku
lisää matkalaukun lastiruumaan
toString
palauttaa merkkijonon tyyliin "2 matkalaukkua (7 kg)"
Tallenna matkalaukut sopivaan ArrayList
-rakenteeseen.
Luokan Lastiruuma
tulee valvoa,
että sen matkalaukkujen yhteispaino ei ylitä maksimikapasiteettia.
Jos maksimikapasiteetti ylittyisi uuden matkalaukun vuoksi,
metodi lisaaMatkalaukku
ei lisää matkalaukkua.
Käyttöesimerkki:
public class Main { public static void main(String[] args) { Tavara kirja = new Tavara("Aapiskukko", 2); Tavara puhelin = new Tavara("Nokia 3210", 1); Tavara tiiliskivi = new Tavara("tiiliskivi", 4); Matkalaukku matinLaukku = new Matkalaukku(10); matinLaukku.lisaaTavara(kirja); matinLaukku.lisaaTavara(puhelin); Matkalaukku pekanLaukku = new Matkalaukku(10); pekanLaukku.lisaaTavara(tiiliskivi); Lastiruuma lastiruuma = new Lastiruuma(1000); lastiruuma.lisaaMatkalaukku(matinLaukku); lastiruuma.lisaaMatkalaukku(pekanLaukku); System.out.println(lastiruuma); } }
Ohjelman tulostuksen tulisi olla seuraava:
2 matkalaukkua (7 kg)
Lisää luokkaan Lastiruuma
metodi
tulostaTavarat
, joka tulostaa kaikki
lastiruuman matkalaukuissa olevat tavarat.
Käyttöesimerkki:
public class Main { public static void main(String[] args) { Tavara kirja = new Tavara("Aapiskukko", 2); Tavara puhelin = new Tavara("Nokia 3210", 1); Tavara tiiliskivi = new Tavara("tiiliskivi", 4); Matkalaukku matinLaukku = new Matkalaukku(10); matinLaukku.lisaaTavara(kirja); matinLaukku.lisaaTavara(puhelin); Matkalaukku pekanLaukku = new Matkalaukku(10); pekanLaukku.lisaaTavara(tiiliskivi); Lastiruuma lastiruuma = new Lastiruuma(1000); lastiruuma.lisaaMatkalaukku(matinLaukku); lastiruuma.lisaaMatkalaukku(pekanLaukku); System.out.println("Ruuman matkalaukuissa on seuraavat tavarat:"); lastiruuma.tulostaTavarat(); } }
Ohjelman tulostuksen tulisi olla seuraava:
Ruuman matkalaukuissa on seuraavat tavarat: Aapiskukko (2 kg) Nokia 3210 (1 kg) tiiliskivi (4 kg)
Testataan vielä, että lastiruuman toiminta on oikea eikä maksimipaino pääse ylittymään. Tee ohjelma, joka lisää lastiruumaan 100 matkalaukkua, joissa jokaisessa on yksi tiiliskivi. Tiiliskivien painot ovat 1, 2, 3, ..., 100 kg.
Ohjelman runko on seuraava:
public class Main { public static void main(String[] args) { Lastiruuma lastiruuma = new Lastiruuma(1000); // 100 matkalaukun lisääminen System.out.println(lastiruuma); } }
Ohjelman tulostuksen tulisi olla seuraava:
44 matkalaukkua (990 kg)
Kun jokin ohjelmointikielen väline vaikuttaa helppokäyttöiseltä ja joustavalta, kyseessä on se, että joku on toteuttanut eli ohjelmoinut, tuon helppouden! Eikä se välttämättä ole ollut helppoa...
Luokassa String on monenlaisia välineitä merkkijonojen käsittelyyn. Kerran luotu String-olio tunnetusti ei kuitenkaan voi koskaan muuttua – String-oliot ovat kerran synnyttyään muuttumattomia, "immutaabeleita".
Tässä tehtäväsarjassa toteutetaan vaiheittain merkkijonoluokka MyString muutettavien merkkijononojen toteutukseksi. Tehtävienn ratkaisemisessa on pyrittävä välttämään roskienkerääjän ylensyöttämistä. Itse asiassa Java-APIssa on olemassa luokat StringBuilder ja StringBuffer muutettavien merkkijonojen käsittelyyn, mutta asioiden tekeminen omin käsin on opettavaista! Näiden tehtävien ratkaisussa ei saa käyttää StringBuilder- ja StringBuffer-olioita eikä aluksi myöskään ArrayList-olioa. Myöskään – sinänsä ovelaa ideaa! &ndash muuntaa merkkitaulukko String-olioksi ja toteuttaa kaikki MyString-operaatiot String-operaatioin ei saa käyttää, koska silloin ruokittaisiin aivan tarpeettomasti roskienkerääjää. (Ymmärsitkö äskeisen lauseen? Hienoa ja hyvä merkki, jos ymmärsit!)
MyString-luokka kapseloi sisäänsä merkkitaulukon, jonka alkuosassa säilytetään esitettävää merkkijonoa. Luokan määrittely alkaa seuraavasti:
public class MyString { public static final int MAKSIMIPITUUS = 100; // - pisin mahdollinen merkkijono // - näkyy kaikkialle ilmauksella: MyString.MAKSIMIPITUUS private char[] mjono; // - merkkijononon esitys char-taulukkona private int pituus; // - montako alkioita mjono:n alusta on käytössä ... // eli ensimmäisen käyttämättömän alkion indeksi // - tyhjässä MyString-oliossa arvo on siis 0 }
Määrejono public static final
määrää, että
kenttä MAKSIMIPITUUS
näkyy kaikkialle, että
se liittyy luokkaan, ei olioon, ja että sen arvoa ei voi muuttaa.
Tällaiset nimetyt vakiot on tapana kirjoittaa isoin kirjaimin.
Toteutetaan ensin seuraava hyvin suppea API:
pituus
, ei taulukon mjono
pituus.
Vihje: Voisi ajatella, että ensin tekisi koko char-taulukosta
Stringin, sitten muistelisi String-aksessoria
substring vaikkapa materiaalin
toisen pääluvun aliluvusta 23.
Kokeile ja esittele MyStringin käyttöä pienellä ohjelmalla.
Täydennä MyStringin toteutusta seuraavilla välineillä:
pituus-1
.
Virheellinen indeksointi aiheuttaa
poikkeuksen, jonka voi heittää vaikkapa lauseella
throw new IndexOutOfBoundsException("charAt-operaatiossa");
index
merkin uudella.
Sallitut indeksin arvot ovat
0—pituus-1
.
Virheellinen indeksointi aiheuttaa
poikkeuksen, jonka voi heittää vaikkapa lauseella
throw new IndexOutOfBoundsException("replace-operaatiossa");
old
-merkit
new
-merkeillä.
Kokeile ja esittele kehitellyn MyStringin käyttöä pienellä ohjelmalla.
Täydennä MyStringin toteutusta seuraavilla välineillä:
index
.
Virheellinen indeksointi aiheuttaa
poikkeuksen, jonka voi heittää vaikkapa lauseella
throw new IndexOutOfBoundsException("deleteCharAt-operaatiossa");
Huomaa, että poistettua merkkiä seuranneet merkit myös pitää siirtää
taulukon alkua kohden.
offset
on se indeksi, jonka
kohtaan merkki lisätään. Tuolloin siis merkkijonon loppuosaa joudutaan
siirtämään yhtä pykälää edemmäksi.
Sallitut lisäyskohdat ovat siis 0–pituus
ettei mennä mjono
-taulukon omasta ylärjasta yli.
Virheellinen indeksointi aiheuttaa
poikkeuksen, jonka voi heittää vaikkapa lauseella
throw new IndexOutOfBoundsException("insert-operaatiossa");
Sama poikkeus heitetään myös, jos yritetään lisätä merkki maksimipituiseen
MyString-olioon.
Kokeile ja esittele kehitellyn MyStringin käyttöä pienellä ohjelmalla.
Täydennä MyStringin toteutusta String-luokasta tutuin aksessorein compareTo ja indexOf(char). Poiketen String luokan compareTo-metodista riittää, että MyStringin compareTo-metodi palauttaa vain jonkin arvoista -1, 0 tai 1.
Kokeile ja esittele kehitellyn MyStringin käyttöä pienellä ohjelmalla.
Täydennä MyStringin toteutusta String-luokasta tutulla aksessorilla indexOf(MyString).
Kokeile ja esittele kehitellyn MyStringin käyttöä pienellä ohjelmalla.
Toteuta vähintään vaiheen 3 (tämän sarjan 3. tehtävä) vahvuinen MyString siten, että piilossa pidetty tietorakenne ei olekaan char-taulukko vaan ArrayList<Character>-olio. Voit samalla luopua MyString-olion pituusrajoituksesta. Ja jos nyt tälle tielle lähdit, mikset toteuttasi vaiheen 5 versiotakin. ;-) Ei ole pakko...