Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Osan kaikki tehtävät

huomautus

Jos palautat tehtävät ennen osan takarajaa (ma 23.2.2026 klo 11:59 (keskipäivä)), voit saada DL-BONUS-pisteitä harjoitustehtäviin. Lue lisää suorittaminen-sivulta.

Tehtävä 6.1: Laskukone 1 p.

Tee ohjelma, joka kysyy käyttäjältä kaksi desimaalilukua sekä laskutoimituksen ja tulostaa lopputuloksen seuraavasti:

Luku 1 > 12.0
Luku 2 > 3.0
Laskutoimitus (+, -, *, /) > +
12.0 + 3.0 = 15.0

Tässä vaiheessa sinun ei tarvitse käsitellä virheellisiä syötteitä, vaan voit olettaa, että luvut annetaan aina lukuina. Sallitut laskutoimitukset ovat summa (+), erotus (-), tulo (*) ja osamäärä (/). Voit olettaa, että vain näitä laskutoimituksia käytetään syötteenä.

Älä käytä silmukoita tai ehtorakenteita. Sen sijaan toteuta laskutoimitukset lambdalausekkeina ja tallenna ne hakurakenteeseen käyttäen laskutoimituksen merkkiä avaimena.

Ohjelman suoritus päättyy tuloksen näyttämisen jälkeen.

Vinkki 1

Voit käyttää lambdalausekkeiden tyyppinä BiFunction<Double, Double, Double> (JavaDoc) tai DoubleBinaryOperator (JavaDoc).

Vinkki 2

Voit käyttää hakurakenteen tyyppinä Map<String, BiFunction<Double, Double, Double>> tai Map<String, DoubleBinaryOperator>.

Voit joko valita hakurakenteelle tietyn toteutuksen tai alustaa muuttumattoman hakurakenteen Map.of-metodilla:

Map<String, BiFunction<Double, Double, Double>> laskutoimitukset = Map.of(
    "+", ...,
    "-", ...,
    "*", ...,
    "/", ...
);

...-kohdan tilalle riittää asettaa sopiva lambdalauseke.

Tee tehtävä TIMissä
Tehtävä 6.2: Vertailu harvinaisuuden mukaan 1 p.

Laajenna Kerailykortti-luokkaa lisäämällä sille attribuutti String harvinaisuus. Keräilykortin harvinaisuus voi olla yksi seuraavista arvoista (vähiten harvinaisesta harvinaisimpaan): C, U, R, RR, RRR, SR, AR, SAR, UR.

Kirjoita vertailija, joka järjestää listassa olevat kortit niiden harvinaisuuden mukaan. Voit käyttää seuraavaa valmista korttikokoelmaa koodisi testaamiseen:

Mallilista erilaisista korteista
List<Kerailykortti> kortit = new ArrayList<>(List.of(
    new Kerailykortti("Kadonnut Puolipiste", "Koodiviidakko", 101, "C"),
    new Kerailykortti("Loputon Silmukka", "Koodiviidakko", 102, "U"),
    new Kerailykortti("Bugimetsästäjä", "Koodiviidakko", 103, "R"),
    new Kerailykortti("Spagettikoodi-Hirviö", "Koodiviidakko", 104, "RR"),
    new Kerailykortti("Ylikellotettu Prosessori", "Koodiviidakko", 105, "SR"),
    new Kerailykortti("Pyhä Stack Overflow", "Koodiviidakko", 106, "RRR"),
    new Kerailykortti("Null Pointer -Ninja", "Koodiviidakko", 107, "U"),
    new Kerailykortti("Sininen Kuolemanruutu", "Koodiviidakko", 108, "AR"),

    new Kerailykortti("Opiskelijakortti", "Kampus-Saaga", 201, "C"),
    new Kerailykortti("Unelias Luennoitsija", "Kampus-Saaga", 202, "C"),
    new Kerailykortti("Haalaribileet", "Kampus-Saaga", 203, "U"),
    new Kerailykortti("Ylisuorittaja", "Kampus-Saaga", 204, "R"),
    new Kerailykortti("Ilmainen Ämpäri", "Kampus-Saaga", 205, "SAR"),
    new Kerailykortti("Myöhästynyt Palautus", "Kampus-Saaga", 206, "RR"),
    new Kerailykortti("Akateeminen Vartti", "Kampus-Saaga", 207, "SR"),
    new Kerailykortti("Gradu-Ahdistus", "Kampus-Saaga", 208, "AR"),
    new Kerailykortti("Semman Pannukakku", "Kampus-Saaga", 209, "UR"),

    new Kerailykortti("Vihainen Hirvi", "Suomi-Myytit", 301, "C"),
    new Kerailykortti("Ikuinen Marraskuu", "Suomi-Myytit", 302, "RR"),
    new Kerailykortti("Saunaklonkku", "Suomi-Myytit", 303, "SR"),
    new Kerailykortti("Salmiakkisade", "Suomi-Myytit", 304, "U"),
    new Kerailykortti("Väinämöisen Kantele", "Suomi-Myytit", 305, "SAR"),
    new Kerailykortti("Sisu", "Suomi-Myytit", 306, "RRR"),
    new Kerailykortti("Laser-Löylykauha", "Suomi-Myytit", 307, "UR"),
    new Kerailykortti("Toripoliisi", "Suomi-Myytit", 308, "R")
));

Kirjoita main()-ohjelma, joka järjestää ja tulostaa keräilykortit harvinaisuuden mukaan (yleisimmät kortit ensin, harvinaisimmat viimeiseksi). Kortit, joiden harvinaisuus on jokin muu kuin yllä mainitut tai null, tulee sijoittaa listan alkuun.

Tee tehtävä TIMissä
Tehtävä 6.3: Musiikkilista 1 p.

Olkoon käytössä luokka Kappale, joka edustaa yksittäistä musiikkikappaletta. Kappaleella on nimi, genre ja kesto sekunteina:

class Kappale {
    String nimi;
    String genre;
    int kestoSekunteina;
}

Lisää luokalle tarvittavat näkyvyysmääreet, muodostaja, tarpeelliset saantimetodit (getterit) sekä sopiva toString()-metodin toteutus.

Tee funktio teeSoittolista(kappaleet, genre, kappaleita), joka palauttaa korkeintaan kappaleita-muuttujan ilmoittaman määrän kappaleita, joiden genre vastaa annettua genre-parametria. Kappaleiden tulee olla järjestettynä keston mukaan lyhyemmästä pisimpään.

Voit käyttää seuraavaa mallilistaa koodisi testaamiseen:

Lista mallikappaleista
List<Kappale> biisilista = List.of(
    new Kappale("Bohemian Rhapsody", "Rock", 354),
    new Kappale("Levitating", "Pop", 203),
    new Kappale("Sandstorm", "Electronic", 225),
    new Kappale("Paranoid", "Metal", 168),
    new Kappale("Toxic", "Pop", 198),
    new Kappale("Master of Puppets", "Metal", 515),
    new Kappale("Cha Cha Cha", "Pop", 175),
    new Kappale("Hotel California", "Rock", 390),
    new Kappale("Stay", "Pop", 141),
    new Kappale("Enter Sandman", "Metal", 331),
    new Kappale("Bad Romance", "Pop", 295),
    new Kappale("Midnight City", "Electronic", 243),
    new Kappale("Billie Jean", "Pop", 294),
    new Kappale("Hard Rock Hallelujah", "Metal", 247),
    new Kappale("Thriller", "Pop", 357),
    new Kappale("As It Was", "Pop", 167),
    new Kappale("Paint It, Black", "Rock", 202),
    new Kappale("Hollywood Hills", "Rock", 210),
    new Kappale("Get Lucky", "Electronic", 369),
    new Kappale("Shake It Off", "Pop", 219),
    new Kappale("Ace of Spades", "Metal", 169),
    new Kappale("Rolling in the Deep", "Pop", 228),
    new Kappale("Sweet Child O' Mine", "Rock", 356),
    new Kappale("Borderline", "Pop", 210),
    new Kappale("Back in Black", "Rock", 255),
    new Kappale("Shape of You", "Pop", 233),
    new Kappale("Fear of the Dark", "Metal", 438),
    new Kappale("Blinding Lights", "Pop", 200),
    new Kappale("Stairway to Heaven", "Rock", 482),
    new Kappale("Uptown Funk", "Pop", 269),
    new Kappale("Smells Like Teen Spirit", "Rock", 301),
    new Kappale("Short Pop Song", "Pop", 120)
);

Älä käytä silmukoita, vaan toteuta teeSoittolista käyttäen striimejä.

Vinkki

Saatat tarvita ainakin seuraavia Stream-metodeja:

  • filter(): alkioiden suodatus
  • sorted(): alkioiden järjestäminen
  • limit(): alkioiden lukumäärän rajaaminen
  • toList(): alkioiden kerääminen listaksi
Tee tehtävä TIMissä
Tehtävä 6.4: Keskiarvo raja-arvoilla 1 p.

Tee funktio double keskiarvo(int[] luvut, int minimi, int maksimi). Funktio laskee taulukkona annettujen lukujen keskiarvon seuraavilla ehdoilla:

  • Jos alkio on pienempi tai yhtä suuri kuin minimi, alkio hylätään eikä sitä lasketa keskiarvoon mukaan.
  • Jos alkio on suurempi tai yhtä suuri kuin maksimi, kyseinen alkio ja kaikki sen jälkeen tulevat alkiot hylätään.

Esimerkki:

IO.println(keskiarvo(new int[] { -5, 1, -4, 0, 98 }, -7, 99));
IO.println(keskiarvo(new int[] { 11, 4, 2, 6, 99, 12, 0, -3 }, 3, 99));
IO.println(keskiarvo(new int[] { 99, 1, 2, 3 }, 0, 99));
18.0
7.0
0.0

Ensimmäinen kutsu palauttaa 18.0, sillä aineisto on kokonaisuudessaan minimin ja maksimin välissä. Toinen kutsu palauttaa taas 7.0, sillä vain luvut 11, 4 ja 6 otetaan keskiarvoon mukaan: luku 2 on pienempi kuin minimi ja kaikki luvusta 99 alkaen hylätään.

Jos keskiarvoa ei voida laskea, funktio palauttaa minimi-parametrin arvon.

Älä käytä silmukoita, vaan toteuta funktio käyttäen striimejä.

Vinkki

Tutustu IntStream-tyyppiin (JavaDoc) ja sen metodeihin. Voit hyötyä ainakin seuraavista:

  • filter(): alkioiden suodattaminen pois striimistä
  • takeWhile(): ottaa alkioita striimistä niin kauan kuin ehto on tosi; heti kun ehto on epätosi, striimin käsittely loppuu siihen (kuin "hana", joka suljetaan).
  • average(): laskee keskiarvon

Huomaa, että average() palauttaa OptionalDouble-olion (JavaDoc). Olio sisältää orElse()-metodin, jonka avulla voit palauttaa joko lasketun arvon tai vaihtoehtoisen oletusarvon.

Bonustieto

Samankaltainen tehtävä tehdään Ohjelmointi 1 -kurssilla käyttäen silmukoita (ks. Ohjelmointi 1: demo 6, tehtävä B1). Jos olet suorittanut kyseisen kurssin, voit verrata striimeillä tehtyä ratkaisuasi aiemmin tekemääsi silmukkaratkaisuun.

Tee tehtävä TIMissä
Tehtävä 6.5 : Poikkeukset, osa 1. 1 p.

Tee monivalintatehtävä TIMissä.

Tee tehtävä TIMissä
Tehtävä 6.6: Poikkeukset, osa 2. 1 p.

Tee main, joka lukee käyttäjältä silmukassa kokonaislukuja niin kauan, kuin käyttäjä antaa muun kuin tyhjän syötteen. Jos käyttäjä antaa muun kuin kokonaisluvun, tulosta virheilmoitus ja jatka lukemista.

Tallenna luvut taulukkoon. Tulosta lopuksi kaikki taulukkoon tallennetut luvut.

Tee tehtävä TIMissä
Tehtävä 6.7: Poikkeukset, osa 3. 1 p.

Tee ohjelma, joka tarkistaa, onko käyttäjän syöttämä ikä riittävä tiettyyn toimintaan, esimerkiksi ajokortin hankkimiseen.

Tee aliohjelma onkoIkaa, joka ottaa parametrina iän (int) ja palauttaa true, jos ikä on riittävä. Jos ikä on alle 18, heitä poikkeus IkaException, joka on oma tarkastettu poikkeusluokka. Anna sopiva poikkeusviesti, esimerkiksi "Ikä ei riitä.". Ohessa vinkiksi metodin esittelyrivi.

static boolean onkoIkaa(int ika) throws IkaException

Jos ikä on negatiivinen, heitä poikkeus IkaException viestillä "Ikä ei voi olla negatiivinen.".

Poista if-rakenne ja muokkaa main-metodia niin, että se kääntyy ja tulostaa oikeat asiat.

Tee tehtävä TIMissä
Tehtävä 6.8: Riippuvuudet. 1 p.

Tee uusi Maven-projekti. Aseta pakkauksen nimeksi fi.jyu.omatunnus (laita omatunnus-kohdalle JY-käyttäjätunnus tai jokin muu keksimäsi käyttäjänimi). Anna pääluokan nimeksi Riippuvuudet. Lisää siihen tämä koodi.

void main() {
    JSONObject json = new JSONObject();
    json.put("nimi", "Maija");
    json.put("ika", 25);
    IO.println(json.getString("nimi"));
    IO.println(json.getInt("ika"));
}

Lisää nyt pom.xml-tiedostoon riippuvuus json-nimiseen artefaktiin. Etsi tämä kirjasto Maven Centralista, ja kopioi sieltä XML-koodi pom.xml-tiedostoosi. Lisää myös riippuvuuden vaatima import-lause luokan alkuun.

Käännä ja aja ohjelma, ja varmista, että se tulostaa odotetut tiedot.

Tee tehtävä TIMissä
Tehtävä 6.9: Sanat. 1 p.

Lataa aineisto: sanat.txt

Tallenna tiedosto projektisi työskentelyhakemistoon nimellä sanat.txt.

Tiedostossa on yksi sana per rivi. Mukana on tarkoituksella tyhjiä rivejä, välilyöntejä sanojen alussa/lopussa, samoja sanoja useaan kertaan, eri kirjainkokoja (esim. Java, java, JAVA).

Esimerkki aineiston alusta:

  Java
python

JAVA
CSharp
  java  

Tee ohjelma, joka:

  • Lukee kaikki rivit.
  • Poistaa sanoista ylimääräiset välilyönnit ja muuttaa sanat pieniksi kirjaimiksi. Vinkki: String.trim() ja String.toLowerCase().
  • Poistaa tyhjät rivit.
  • Poistaa duplikaatit. (Vinkki: distinct()-metodi Stream API:lla, tai Set-kokoelma.)
  • Järjestää sanat aakkosjärjestykseen. (Vinkki: sorted()-metodi Stream API:lla, tai Collections.sort()-metodi Listalla.)
  • Kirjoittaa uuden tiedoston output/sanat-siisti.txt, jossa on siistitty sanalista (yksi sana per rivi).
  • Kirjoittaa lisäksi tiedoston output/raportti.txt, jossa on:
    • alkuperäisten rivien määrä
    • uniikkien sanojen määrä sen jälkeen, kun tyhjät rivit on poistettu ja sanat on siistitty
    • pisin sana (jos useita, mikä tahansa kelpaa). Vinkki: Jos ratkaiset tehtävän Stream API:lla, voit käyttää Stream.max(Comparator)-metodia pisimmän sanan löytämiseen.

Vinkki: tee ensin List<String> siistit = ..., ja kirjoita lopuksi Files.write(...) kahteen eri tiedostoon.

raportti.txt:n pitäisi näyttää tältä:

Alkuperäisiä rivejä: 1074
Siistittyjä sanoja: 59
Pisin sana: binarytree
Tee tehtävä TIMissä
Tehtävä 6.10: Lue henkilöt JSON-tiedostosta. 1 p.

EDIT 23.2.2026: Jackson-kirjaston riippuvuuksia ja esimerkkejä päivitetty materiaalissa. Pahoittelut virheistä.

  1. Tee uusi Maven-projekti, joka käyttää Jackson-kirjastoa JSON-tiedostojen käsittelyyn.
  2. Lisää pom.xml-tiedostoosi tarvittava riippuvuus.
  3. Lataa henkilot.json ja tallenna se projektiisi samaan kansioon kuin missä koodisi on.
  4. Henkilo-luokka tai vastaava record, jolla on kentät String nimi, int ika, String kaupunki.
  5. Lue tiedosto henkilot.json ja muuta se listaksi Henkilo-olioita.
  6. Suodata mukaan vain vähintään 18-vuotiaat.
  7. Tulosta heidän nimensä, ikänsä ja kaupunkinsa.

Muista varmistaa, että tallennat henkilot.json-tiedoston samaan kansioon kuin missä koodisi sijaitsee. Tarkista sitten ajokonfiguraatiostasi, että työskentelyhakemisto on sama kuin koodisi kansio, jotta tiedosto löytyy.

Saat henkilöiden tiedot tarvittaessa auki tästä:

henkilot.json

[ { "nimi": "Maija Laine", "ika": 25, "kaupunki": "Jyväskylä" }, { "nimi": "Matti Virtanen", "ika": 30, "kaupunki": "Tampere" }, { "nimi": "Liisa Niemi", "ika": 17, "kaupunki": "Helsinki" }, { "nimi": "Pekka Korhonen", "ika": 41, "kaupunki": "Oulu" }, { "nimi": "Aino Salmi", "ika": 22, "kaupunki": "Turku" }, { "nimi": "Jari Heikkinen", "ika": 19, "kaupunki": "Kuopio" }, { "nimi": "Sari Lehto", "ika": 16, "kaupunki": "Lahti" }, { "nimi": "Oskari Mäkinen", "ika": 28, "kaupunki": "Espoo" }, { "nimi": "Emilia Ranta", "ika": 33, "kaupunki": "Vantaa" }, { "nimi": "Teemu Koski", "ika": 45, "kaupunki": "Pori" }, { "nimi": "Noora Aalto", "ika": 18, "kaupunki": "Joensuu" }, { "nimi": "Kalle Hämäläinen", "ika": 52, "kaupunki": "Rovaniemi" } ]

Tee tehtävä TIMissä
Bonus: Tehtävä 6.11: CSV -> JSON. 1 p.

EDIT 23.2.2026: Jackson-kirjaston riippuvuuksia ja esimerkkejä päivitetty materiaalissa. Pahoittelut virheistä.

Tee ohjelma, joka lukee tiedoston henkilot.csv (muoto nimi,ika,kaupunki) ja kirjoittaa siitä saman tapainen JSON-tiedoston henkilot.json kuin edellisessä tehtävässä oli annettu valmiiksi. Jos rivi on virheellinen (esim. ikä ei ole numero), ohita rivi ja jatka käsittelyä.

Tulostiedoston pitäisi näyttää tältä. Ei haittaa, jos sisennykset tai rivinvaihdot eivät ole täsmälleen samanlaisia.

[
  {
    "nimi": "Maija Laine",
    "ika": 25,
    "kaupunki": "Jyväskylä"
  },
  {
    "nimi": "Matti Virtanen",
    "ika": 30,
    "kaupunki": "Tampere"
  },
  ...
]
Tee tehtävä TIMissä
Bonus: Tehtävä 6.12: Parempi laskukone 1 p.

Tee yksinkertainen laskinohjelma, joka kysyy käyttäjältä toistuvasti kaksi lukua sekä laskutoimituksen ja tulostaa laskutoimituksen tuloksen.

Ohjelman tulisi toimia suunnilleen seuraavasti:

Anna laskutoimitus muodossa <luku> <operaattori> <luku>.
Kirjoita "sulje" sulkeaksesi ohjelman.

> 1 + 1
2.0
> 10 - 1
9.0
> 0.5 * 100
50.0
> 10 / 2
5.0
> 10
Anna laskutoimitus muodossa <luku> <operaattori> <luku>.
> kissa
Anna laskutoimitus muodossa <luku> <operaattori> <luku>.
> sulje
Ohjelma sulkeutuu.

Ohjelman on käsiteltävä käyttäjän syötteessä olevat virheet siten, ettei ohjelma kaadu virheellisen syötteen vuoksi.

Toteuta peruslaskutoimituksista summa (+), erotus (-), tulo (*) ja osamäärä (/). Keksi lisäksi vähintään kaksi omaa vapaavalintaista laskutoimitusta ja toteuta ne.

Älä käytä ehtorakenteita varsinaisten laskutoimitusten valitsemiseen. Voit kuitenkin käyttää ehtorakenteita sekä try/catch-rakenteita syötteen oikeellisuuden tarkistamiseen.

Vinkki 1

Voit toteuttaa operaatiot lambdalausekkeina. Käytä lambdalausekkeiden tyyppinä BiFunction<Double, Double, Double> (JavaDoc) tai DoubleBinaryOperator (JavaDoc).

Vinkki 2

Voit käyttää Scanner-luokkaa käyttäjän syötteen lukemiseen:

Scanner lukija = new Scanner(kayttajanSyote);

double luku1 = lukija.nextDouble();
String laskutoimitus = lukija.next();
double luku2 = lukija.nextDouble();

Saatat joutua lisäämään tarvittavat poikkeustenkäsittelyt.

Tee tehtävä TIMissä