Osa 4

Oliot listalla

Listalle lisättävien muuttujien tyyppi määrätään listan luomisen yhteydessä annettavan tyyppiparametrin avulla. Esimerkiksi ArrayList<String> sisältää merkkijonoja, ArrayList<Integer> sisältää kokonaislukuja, ja ArrayList<Double> sisältää liukulukuja.

Alla olevassa esimerkissä lisätään ensin merkkijonoja listalle, jonka jälkeen listalla olevat merkkijonot tulostetaan yksitellen.

ArrayList<String> nimet = new ArrayList<>();

// merkkijono voidaan lisätä ensin muuttujaan
String nimi = "Betty Jennings";
// ja sitten lisätä se listalle
nimet.add(nimi);

// merkkijono voidaan myös lisätä suoraan listalle:
nimet.add("Betty Snyder");
nimet.add("Frances Spence");
nimet.add("Kay McNulty");
nimet.add("Marlyn Wescoff");
nimet.add("Ruth Lichterman");

// listan alkioiden läpikäynti onnistuu useamman erilaisen
// toistolauseen avulla

// 1. while-toistolause
int indeksi = 0;
while (indeksi < nimet.size()) {
    System.out.println(nimet.get(indeksi));
    indeksi = indeksi + 1;
}

// 2. for-toistolause indeksillä
for (int i = 0; i < nimet.size(); i++) {
    System.out.println(nimet.get(i));
}

System.out.println();
// 3. for-each toistolause (ei indeksiä)
for (String nimi: nimet) {
    System.out.println(nimi);
}
Esimerkkitulostus

Betty Jennings Betty Snyder Frances Spence Kay McNulty Marlyn Wescoff Ruth Lichterman

Betty Jennings Betty Snyder Frances Spence Kay McNulty Marlyn Wescoff Ruth Lichterman

Betty Jennings Betty Snyder Frances Spence Kay McNulty Marlyn Wescoff Ruth Lichterman

Olioiden lisääminen listalle

Merkkijonot ovat olioita, joten ei liene yllätys että listalla voi olla muunkinlaisia olioita. Tarkastellaan seuraavaksi listan ja olioiden yhteistoimintaa tarkemmin.

Oletetaan, että käytössämme on alla oleva henkilöä kuvaava luokka.

public class Henkilo {

    private String nimi;
    private int ika;
    private int paino;
    private int pituus;

    public Henkilo(String nimi) {
        this.nimi = nimi;
        this.ika = 0;
        this.paino = 0;
        this.pituus = 0;
    }

    public String getNimi() {
        return this.nimi;
    }

    public int getIka() {
        return this.ika;
    }

    public void vanhene() {
        this.ika = this.ika + 1;
    }

    public void setPituus(int uusiPituus) {
        this.pituus = uusiPituus;
    }

    public void setPaino(int uusiPaino) {
        this.paino = uusiPaino;
    }

    public double painoindeksi() {
        double pituusPerSata = this.pituus / 100.0;
        return this.paino / (pituusPerSata * pituusPerSata);
    }

    @Override
    public String toString() {
        return this.nimi + ", ikä " + this.ika + " vuotta";
    }
}

Olioiden käsittely listalla ei oikeastaan poikkea aiemmin näkemästämme listan käytöstä millään tavalla. Oleellista on vain listalle lisättävien olioiden tyypin määrittely listan luomisen yhteydessä.

Alla olevassa esimerkissä luodaan ensin Henkilo-tyyppisille olioille tarkoitettu lista, jonka jälkeen listalle lisätään henkilöolioita. Lopulta henkilöoliot tulostetaan yksitellen.

ArrayList<Henkilo> henkilot = new ArrayList<>();

// henkilöolio voidaan ensin luoda
Henkilo juhana = new Henkilo("Juhana");
// ja sitten lisätä se listalle
henkilot.add(juhana);

// henkilöolio voidaan myös lisätä listalle "samassa lauseessa"
henkilot.add(new Henkilo("Matti"));
henkilot.add(new Henkilo("Martin"));

for (Henkilo henkilo: henkilot) {
    System.out.println(henkilo);
}
Esimerkkitulostus

Juhana, ikä 0 vuotta Matti, ikä 0 vuotta Martin, ikä 0 vuotta

Käyttäjän syöttämät oliot listalle

Aiemmin käyttämämme rakenne syötteiden lukemiseen on yhä varsin käytännöllinen.

Scanner lukija = new Scanner(System.in);
ArrayList<Henkilo> henkilot = new ArrayList<>();

// Luetaan henkilöiden nimet käyttäjältä
while (true) {
    System.out.print("Kirjoita nimi, tyhjä lopettaa: ");
    String nimi = lukija.nextLine();
    if (nimi.isEmpty()) {
        break;
    }

    // Lisätään listalle uusi henkilo-olio, jonka
    // nimi on käyttäjän syöttämä
    henkilot.add(new Henkilo(nimi));
}

// Tulostetaan syötettyjen henkilöiden määrä sekä henkilöt
System.out.println();
System.out.println("Henkilöitä yhteensä: " + henkilot.size());
System.out.println("Henkilöt: ");

for (Henkilo henkilo: henkilot) {
    System.out.println(henkilo);
}
Esimerkkitulostus

Kirjoita nimi, tyhjä lopettaa: Alan Kay Kirjoita nimi, tyhjä lopettaa: Ivan Sutherland Kirjoita nimi, tyhjä lopettaa: Kristen Nygaard

Henkilöitä yhteensä: 3 Henkilöt: Alan Kay, ikä 0 vuotta Ivan Sutherland, ikä 0 vuotta Kristen Nygaard, ikä 0 vuotta

Loading

Useamman arvon lukeminen

Mikäli luokan konstruktori vaatii useampia parametreja, voi käyttäjältä kysyä enemmän tietoa. Oletetaan, että luokan Henkilo konstruktori on seuraavanlainen.

public class Henkilo {

    private String nimi;
    private int ika;
    private int paino;
    private int pituus;

    public Henkilo(String nimi, int ika) {
        this.nimi = nimi;
        this.ika = ika;
        this.paino = 0;
        this.pituus = 0;
    }

    // metodit
}

Olion luominen vaatii siis kaksiparametrisen konstruktorin kutsumista.

Mikäli haluamme lukea tällaisia olioita käyttäjältä, tulee lukemisessa kysyä jokainen parametri erikseen. Alla olevassa esimerkissä käyttäjältä luetaan erikseen nimi ja ikä. Mikäli nimi on tyhjä, lukeminen lopetetaan.

Henkilöt tulostetaan lukemisen jälkeen.

Scanner lukija = new Scanner(System.in);
ArrayList<Henkilo> henkilot = new ArrayList<>();

// Luetaan henkilöiden tiedot käyttäjältä
while (true) {
    System.out.print("Kirjoita nimi, tyhjä lopettaa: ");
    String nimi = lukija.nextLine();
    if (nimi.isEmpty()) {
        break;
    }

    System.out.print("Kirjoita henkilön " + nimi + " ikä: ");

    int ika = Integer.valueOf(lukija.nextLine());

    // Lisätään listalle uusi henkilo-olio, jonka
    // nimen ja iän käyttäjä syötti
    henkilot.add(new Henkilo(nimi, ika));
}

// Tulostetaan syötettyjen henkilöiden määrä sekä henkilöt
System.out.println();
System.out.println("Henkilöitä yhteensä: " + henkilot.size());
System.out.println("Henkilöt: ");

for (Henkilo henkilo: henkilot) {
    System.out.println(henkilo);
}
Esimerkkitulostus

Kirjoita nimi, tyhjä lopettaa: Grace Hopper Kirjoita henkilön Grace Hopper ikä: 85 Kirjoita nimi, tyhjä lopettaa:

Henkilöitä yhteensä: 1 Henkilöt: Grace Hopper, ikä 85 vuotta

Loading

Rajattu tulostus listalta

Listalla olevia olioita voidaan myös tarkastella listan läpikäynnin yhteydessä. Alla olevassa esimerkissä käyttäjältä kysytään ensin ikäraja, jonka jälkeen tulostetaan ne oliot, joiden ikä on vähintään käyttäjän syöttämä ikäraja.

// Oletetaan, että käytössämme on henkilot-lista,
// joka sisältää henkilöolioita

System.out.print("Mikä ikäraja? ");
int ikaraja = Integer.valueOf(lukija.nextLine());

for (Henkilo henkilo: henkilot) {
    if (henkilo.getIka() >= ikaraja) {
        System.out.println(henkilo);
    }
}
Loading
Loading
Pääsit aliluvun loppuun! Jatka tästä seuraavaan osaan:

Muistathan tarkistaa pistetilanteesi materiaalin oikeassa alareunassa olevasta pallosta!