Osa 6

Olioita listalla ja listan sisältävät oliot

Tutustutaan seuraavaksi olioihin, jonka sisältävät listan. Tällaisia olioita ovat esimerkiksi joukkoja kuvaavat oliot, kuten vaikkapa soittolistat.

Alla olevassa esimerkissä käsitteelle soittolista on luotu luokka. Soittolista sisältää kappaleita: siihen voi lisätä kappaleita, siitä voi poistaa kappaleita, ja siinä olevat kappaleet voi tulostaa.

// importit

public class Soittolista {
    private ArrayList<String> kappaleet;

    public Soittolista() {
        this.kappaleet = new ArrayList<>();
    }

    public void lisaaKappale(String kappale) {
        this.kappaleet.add(kappale);
    }

    public void poistaKappale(String kappale) {
        this.kappaleet.remove(kappale);
    }

    public void tulostaKappaleet() {
        for (String kappale: this.kappaleet) {
            System.out.println(kappale);
        }
    }
}

Soittolistojen luominen on edellisen luokan avulla helppoa.

Soittolista lista = new Soittolista();
lista.lisaaKappale("Sorateiden kuningas");
lista.lisaaKappale("Teuvo, maanteiden kuningas");
lista.tulostaKappaleet();
Esimerkkitulostus

Sorateiden kuningas Teuvo, maanteiden kuningas

Loading
Loading

Omia olioita oliomuuttujana olevalla listalla

Oliomuuttujana oleva lista voi sisältää merkkijonojen lisäksi myös muunlaisia olioita, kunhan listalla olevien olioiden tyyppi määritellään listan määrittelyn yhteydessä.

Loimme edellisessä osassa luokan Huvipuistolaite, jonka avulla tarkastellaan pääseekö henkilö laitteen kyytiin. Luokka Huvipuistolaite näyttää seuraavalta.

public class Huvipuistolaite {
    private String nimi;
    private int alinPituus;
    private int kavijoita;

    public Huvipuistolaite(String nimi, int alinPituus) {
        this.nimi = nimi;
        this.alinPituus = alinPituus;
        this.kavijoita = 0;
    }

    public boolean paaseeKyytiin(Henkilo henkilo) {
        if (henkilo.getPituus() < this.alinPituus) {
            return false;
        }

        this.kavijoita++;
        return true;
    }

    public String toString() {
        return this.nimi + ", pituusalaraja: " + this.alinPituus +
            ", kävijöitä: " + this.kavijoita;
    }
}

Laajennetaan luokkaa siten, että huvipuistolaite pitää kirjaa kyydissä olevista henkilöistä. Laajennetussa versiossa huvipuistolaitteella on oliomuuttujana lista, joka sisältää laitteeseen päässeet henkilöt. Lista luodaan konstruktorissa.

public class Huvipuistolaite {
    private String nimi;
    private int alinPituus;
    private int kavijoita;
    private ArrayList<Henkilo> kyydissa;

    public Huvipuistolaite(String nimi, int alinPituus) {
        this.nimi = nimi;
        this.alinPituus = alinPituus;
        this.kavijoita = 0;
        this.kyydissa = new ArrayList<>();
    }

    // ..
}

Muokataan seuraavaksi metodia paaseeKyytiin. Metodi lisää listalle ne henkilöt, jotka ovat tarpeeksi pitkiä.

public class Huvipuistolaite {
    private String nimi;
    private int alinPituus;
    private int kavijoita;
    private ArrayList<Henkilo> kyydissa;

    public Huvipuistolaite(String nimi, int alinPituus) {
        this.nimi = nimi;
        this.alinPituus = alinPituus;
        this.kavijoita = 0;
        this.kyydissa = new ArrayList<>();
    }

    public boolean paaseeKyytiin(Henkilo henkilo) {
        if (henkilo.getPituus() < this.alinPituus) {
            return false;
        }

        this.kavijoita++;
        this.kyydissa.add(henkilo);
        return true;
    }

    public String toString() {
        return this.nimi + ", pituusalaraja: " + this.alinPituus +
            ", kävijöitä: " + this.kavijoita;
    }
}
Loading

Listan sisältävän olion tulostaminen

Muokataan seuraavaksi metodia toString siten, että metodin palauttama merkkijono sisältää jokaisen kyydissä olevan henkilön nimen.

public class Huvipuistolaite {
    private String nimi;
    private int alinPituus;
    private int kavijoita;
    private ArrayList<Henkilo> kyydissa;

    // ...

    public String toString() {
        // luodaan listalla olevista henkilöistä merkkijono
        String kyydissaOlijat = "";
        for (Henkilo henkilo: kyydissa) {
            kyydissaOlijat = kyydissaOlijat + henkilo.getNimi() + "\n";
        }

        // palautetaan oliota kuvaava merkkijono,
        // joka sisältää myös kyydissä olijat
        return this.nimi + ", pituusalaraja: " + this.alinPituus +
            ", kävijöitä: " + this.kavijoita + "\n" +
            "kyydissä:\n" + kyydissaOlijat;
    }
}

Kokeillaan laajennettua huvipuistolaitetta:

Henkilo matti = new Henkilo("Matti");
matti.setPaino(86);
matti.setPituus(180);

Henkilo juhana = new Henkilo("Juhana");
juhana.setPaino(34);
juhana.setPituus(132);

Huvipuistolaite hurjakuru = new Huvipuistolaite("Hurjakuru", 140);
System.out.println(hurjakuru);

System.out.println();

if (hurjakuru.paaseeKyytiin(matti)) {
    System.out.println(matti.getNimi() + " pääsee laitteeseen");
} else {
    System.out.println(matti.getNimi() + " ei pääse laitteeseen");
}

if (hurjakuru.paaseeKyytiin(juhana)) {
    System.out.println(juhana.getNimi() + " pääsee laitteeseen");
} else {
    System.out.println(juhana.getNimi() + " ei pääse laitteeseen");
}

System.out.println(hurjakuru);

Ohjelma tulostaa:

Esimerkkitulostus

Hurjakuru, pituusalaraja: 140, kävijöitä: 0 kyydissä:

Matti pääsee laitteeseen Juhana ei pääse laitteeseen Hurjakuru, pituusalaraja: 140, kävijöitä: 1 kyydissä: Matti

Vaikka laitteessa ei ole ketään kyydissä, on tulostuksessa silti merkkijono kyydissä:. Muokataan metodia toString siten, että jos kyydissä ei ole ketään, metodi palauttamassa merkkijonossa on tieto siitä.

public class Huvipuistolaite {
    private String nimi;
    private int alinPituus;
    private int kavijoita;
    private ArrayList<Henkilo> kyydissa;

    public Huvipuistolaite(String nimi, int alinPituus) {
        this.nimi = nimi;
        this.alinPituus = alinPituus;
        this.kavijoita = 0;
        this.kyydissa = new ArrayList<>();
    }

    // ...

    public String toString() {

        String tulostus = this.nimi + ", pituusalaraja: " + this.alinPituus +
            ", kävijöitä: " + this.kavijoita + "\n";

        if (kyydissa.isEmpty()) {
            return tulostus + "ei ketään kyydissä.";
        }

        // luodaan listalla olevista henkilöistä merkkijono
        String kyydissaOlijat = "";

        for (Henkilo henkilo: kyydissa) {
            kyydissaOlijat = kyydissaOlijat + henkilo.getNimi() + "\n";
        }

        return tulostus + "\n" +
            "kyydissä:\n" + kyydissaOlijat;
    }
}

Nyt olion tulostus on parempi.

Henkilo matti = new Henkilo("Matti");
matti.setPaino(86);
matti.setPituus(180);

Henkilo juhana = new Henkilo("Juhana");
juhana.setPaino(34);
juhana.setPituus(132);

Huvipuistolaite hurjakuru = new Huvipuistolaite("Hurjakuru", 140);
System.out.println(hurjakuru);

System.out.println();

if (hurjakuru.paaseeKyytiin(matti)) {
    System.out.println(matti.getNimi() + " pääsee laitteeseen");
} else {
    System.out.println(matti.getNimi() + " ei pääse laitteeseen");
}

if (hurjakuru.paaseeKyytiin(juhana)) {
    System.out.println(juhana.getNimi() + " pääsee laitteeseen");
} else {
    System.out.println(juhana.getNimi() + " ei pääse laitteeseen");
}

System.out.println(hurjakuru);

Ohjelma tulostaa:

Esimerkkitulostus

Hurjakuru, pituusalaraja: 140, kävijöitä: 0 ei ketään kyydissä.

Matti pääsee laitteeseen Juhana ei pääse laitteeseen Hurjakuru, pituusalaraja: 140, kävijöitä: 1 kyydissä: Matti

Loading

Olion sisältämän listan tyhjentäminen

Lisätään huvipuistolaitteelle seuraavaksi metodi poistaKaikkiKyydista, joka poistaa kaikki laitteessa olevat henkilöt laitteen kyydistä. Tässä listan metodi clear on erittäin kätevä.

public class Huvipuistolaite {
    // ..

    public void poistaKaikkiKyydista() {
        this.kyydissa.clear();
    }

    // ..
}
Henkilo matti = new Henkilo("Matti");
matti.setPaino(86);
matti.setPituus(180);

Henkilo juhana = new Henkilo("Juhana");
juhana.setPaino(34);
juhana.setPituus(132);

Huvipuistolaite hurjakuru = new Huvipuistolaite("Hurjakuru", 140);
System.out.println(hurjakuru);

System.out.println();

if (hurjakuru.paaseeKyytiin(matti)) {
    System.out.println(matti.getNimi() + " pääsee laitteeseen");
} else {
    System.out.println(matti.getNimi() + " ei pääse laitteeseen");
}

if (hurjakuru.paaseeKyytiin(juhana)) {
    System.out.println(juhana.getNimi() + " pääsee laitteeseen");
} else {
    System.out.println(juhana.getNimi() + " ei pääse laitteeseen");
}

System.out.println(hurjakuru);

hurjakuru.poistaKaikkiKyydista();

System.out.println();
System.out.println(hurjakuru);

Ohjelma tulostaa:

Esimerkkitulostus

Hurjakuru, pituusalaraja: 140, kävijöitä: 0 ei ketään kyydissä.

Matti pääsee laitteeseen Juhana ei pääse laitteeseen Hurjakuru, pituusalaraja: 140, kävijöitä: 1 kyydissä: Matti

Hurjakuru, pituusalaraja: 140, kävijöitä: 1 ei ketään kyydissä.

Yhteenvetoarvon laskeminen listalla olevista olioista

Tehdään huvipuistolaitteelle seuraavaksi metodi, joka laskee kyydissä olevien henkilöiden keskipituuden. Keskipituus saadaan laskemalla kyydissä olevien keskiarvo — keskiarvo laskettiin selvittämällä lukujen summa ja jakamalla summa lukujen määrällä.

Alla olevassa toteutuksessa palautetaan arvo -1 mikäli kyydissä ei ole yhtäkään henkilöä. Pituuksien keskiarvoa laskevassa ohjelmassa luku -1 on mahdoton, joten siitä voi päätellä ettei keskiarvoa ole voitu laskea.

public class Huvipuistolaite {
    private String nimi;
    private int alinPituus;
    private int kavijoita;
    private ArrayList<Henkilo> kyydissa;

    // ..

    public double kyydissaOlevienKeskipituus() {
        if (kyydissa.isEmpty()) {
            return -1;
        }

        int pituuksienSumma = 0;
        for (Henkilo hlo: kyydissa) {
            pituuksienSumma += hlo.getPituus();
        }

        return 1.0 * pituuksienSumma / kyydissa.size();
    }

    // ..
}
Henkilo matti = new Henkilo("Matti");
matti.setPituus(180);

Henkilo juhana = new Henkilo("Juhana");
juhana.setPituus(132);

Henkilo awak = new Henkilo("Awak");
awak.setPituus(194);

Huvipuistolaite hurjakuru = new Huvipuistolaite("Hurjakuru", 140);

hurjakuru.paaseeKyytiin(matti);
hurjakuru.paaseeKyytiin(juhana);
hurjakuru.paaseeKyytiin(awak);

System.out.println(hurjakuru);
System.out.println(hurjakuru.kyydissaOlevienKeskipituus());

Ohjelma tulostaa:

Esimerkkitulostus

Hurjakuru, pituusalaraja: 140, kävijöitä: 2 kyydissä: Matti Awak 187.0

Loading

Tietyn olion hakeminen listalta

Tehdään seuraavaksi huvipuistolaitteelle metodi, joka palauttaa laitteen kyydissä olevista henkilöistä pisimmän. Metodin tulee siis sekä hakea listalta pisin henkilö, että palauttaa se.

Metodit, jotka hakevat listalta oliota, kannattaa toteuttaa seuraavasti. Ensin katsotaan onko lista tyhjä — mikäli lista on tyhjä, palautetaan null-viite tai joku muu arvo, joka kertoo että listalla ei ollut arvoja. Tämän jälkeen luodaan palautettavaa oliota kuvaava oliomuuttuja, jonka arvoksi asetetaan listan ensimmäinen olio. Tätä seuraa listan arvojen läpikäynti siten, että kutakin listalla olevaa oliota verrataan palautettavaa oliota kuvaavaan oliomuuttujaan. Mikäli vertailussa löydetään hakuun paremmin osuva olio, asetetaan palautettavan olion arvoksi hakuun paremmin osuva olio. Lopulta palautettavaa oliota kuvaava oliomuuttuja palautetaan.

public Henkilo haePisin() {
    // jos kyydissä ei ole ketään, palauta null-viite
    if (this.kyydissa.isEmpty()) {
        return null;
    }

    // luo palautettavaa oliota kuvaava oliomuuttuja,
    // jonka arvoksi asetetaan listan ensimmäinen olio
    Henkilo palautettava = this.kyydissa.get(0);

    // käy lista läpi
    for (Henkilo hlo: this.kyydissa) {
        // vertaa kutakin listalla olevaa oliota
        // palautettavaan -- tässä etsimme pisintä, joten
        // vertailemme pituuksia

        if (palautettava.getPituus() < hlo.getPituus()) {
            // mikäli vertailussa löydetään pidempi henkilö,
            // asetetaan se palautettavan arvoksi
            palautettava = hlo;
        }
    }

    // lopulta palautettavaa oliota kuvaava oliomuuttuja
    // palautetaan
    return palautettava;
}

Nyt pisimmän henkilön löytäminen on helppoa.

Henkilo matti = new Henkilo("Matti");
matti.setPituus(180);

Henkilo juhana = new Henkilo("Juhana");
juhana.setPituus(132);

Henkilo awak = new Henkilo("Awak");
awak.setPituus(194);

Huvipuistolaite hurjakuru = new Huvipuistolaite("Hurjakuru", 140);

hurjakuru.paaseeKyytiin(matti);
hurjakuru.paaseeKyytiin(juhana);
hurjakuru.paaseeKyytiin(awak);

System.out.println(hurjakuru);
System.out.println(hurjakuru.kyydissaOlevienKeskipituus());

System.out.println();
System.out.println(hurjakuru.haePisin().getNimi());
Henkilo pisin = hurjakuru.haePisin();
System.out.println(pisin.getNimi());
Esimerkkitulostus

Hurjakuru, pituusalaraja: 140, kävijöitä: 2 kyydissä: Matti Awak 187.0

Awak Awak

Loading
Loading
Loading
Pääsit aliluvun loppuun! Jatka tästä seuraavaan osaan:

Muistathan tarkistaa pistetilanteesi materiaalin oikeassa alareunassa olevasta pallosta!