7. ArrayList

Tavallisten muuttujien rajoituksena on, että jokaisessa on vain yksi tieto. Jos ohjelman pitää muistaa kolme lukua, tarvitaan kolme muuttujaa. Entä jos ohjelman pitäisi muistaa tuhat lukua tai miljoona lukua?

ArrayList

ArrayList on listarakenne, johon voidaan tallentaa vaihteleva määrä arvoja. Etuna erillisiin muuttujiin verrattuna on, että listaa voidaan käsitellä samanlaisella koodilla riippumatta sen arvojen määrästä.

Listan määrittely

Uusi lista määritellään seuraavalla komennolla:

ArrayList<[tyyppi]> [nimi] = new ArrayList<[tyyppi]>();

Tässä [tyyppi] tarkoittaa, millaisia arvoja listalle voi tallentaa, ja [nimi] on tunnus, jolla listaan viitataan koodissa.

Listan määrittelyssä tyypit eroavat hieman muuttujien tyypistä:

muuttujan määrittelyssälistan määrittelyssä
StringString
intInteger
doubleDouble

Siis String määritellään molemmissa tapauksissa samoin, mutta lukutyyppien määrittelyssä on eroja. Tämä ilmiö saa selityksen myöhemmin, mutta nyt riittää vain tietää asia.

Lisääminen ja hakeminen

Seuraava ohjelma lisää listalle kolme nimeä (Aapeli, Maija ja Väinö). Sitten ohjelma tulostaa nimien määrän ja nimet yksi kerrallaan.

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

nimet.add("Aapeli");
nimet.add("Maija");
nimet.add("Väinö");

System.out.println("Nimien määrä: " + nimet.size());

System.out.println("Eka: " + nimet.get(0));
System.out.println("Toka: " + nimet.get(1));
System.out.println("Kolmas: " + nimet.get(2));

Ohjelman tulostus on seuraava:

Nimien määrä: 3
Eka: Aapeli
Toka: Maija
Kolmas: Väinö

Lista on tallennettu seuraavasti tietokoneen muistiin:

kohta012
sisältö"Aapeli""Maija""Väinö"

Tässä tuli esille kolme listaan liittyvää komentoa:

Huomaa, että listan kohtien numerointi alkaa nollasta. Ensimmäinen arvo on siis kohdassa 0, toinen kohdassa 1 jne.

Onko arvo listalla?

Komennolla contains voi tarkistaa, onko tietty arvo listalla. Seuraavassa esimerkissä listalle laitetaan viikonpäivien nimet suomeksi, ja ohjelma tarkistaa, antaako käyttäjä viikonpäivän nimen.

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

paivat.add("maanantai");
paivat.add("tiistai");
paivat.add("keskiviikko");
paivat.add("torstai");
paivat.add("perjantai");
paivat.add("lauantai");
paivat.add("sunnuntai");

System.out.print("Anna viikonpäivä: ");
String paiva = input.nextLine();

if (paivat.contains(paiva)) {
    System.out.println("Kiitos!");
} else {
    System.out.println("Ei kelpaa!");
}

Esimerkkejä ohjelman suorituksesta:

Anna viikonpäivä: tiistai
Kiitos!
Anna viikonpäivä: selleri
Ei kelpaa!

Esimerkki: Toistuva luku

Seuraava ohjelma kysyy käyttäjältä lukuja, kunnes käyttäjä antaa saman luvun uudestaan. Lopuksi ohjelma tulostaa annettujen lukujen määrän. Ideana on tallentaa kaikki luvut listaan, jotta ohjelma pystyy tarkistamaan, onko käyttäjä antanut saman luvun jo aiemmin.

ArrayList<Integer> lista = new ArrayList<Integer>();

while (true) {
    System.out.print("Anna luku: ");
    int luku = Integer.parseInt(input.nextLine());
    if (lista.contains(luku)) {
        break;
    }
    lista.add(luku);
}
System.out.println("Annoit yhteensä " + lista.size() + " eri lukua.");

Ohjelman suoritus voi olla seuraava:

Anna luku: 3
Anna luku: 5
Anna luku: 2
Anna luku: 9
Anna luku: 5
Annoit yhteensä 4 eri lukua.

Listan läpikäynti

Listan läpikäyntiin on olemassa erityinen for-silmukan muoto, jonka merkintätapa on seuraava:

for ([tyyppi] [muuttuja] : [lista]) {
    [koodi]
}

Tässä [muuttuja] saa arvokseen yksi kerrallaan kunkin listalla olevan arvon. Muuttujan tyypin täytyy vastata listan arvojen tyyppiä.

Seuraava ohjelma tulostaa listan sisällön:

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

nimet.add("Aapeli");
nimet.add("Maija");
nimet.add("Väinö");

for (String nimi : nimet) {
    System.out.println(nimi);
}

Ohjelman tulostus on seuraava:

Aapeli
Maija
Väinö

Listan tulostaminen

Listan sisällön voi myös tulostaa suoraan komennolla System.out.println. Tällöin listan sisältö tulostetaan hakasulkujen sisällä pilkkujen erottamana.

Seuraava ohjelma havainnollistaa asiaa:

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

nimet.add("Aapeli");
nimet.add("Maija");
nimet.add("Väinö");

System.out.println(nimet);

Ohjelman tulostus on seuraava:

[Aapeli, Maija, Väinö]

Muita komentoja

Listan voi järjestää seuraavalla komennolla:

Collections.sort(lista);

Jos listalla on lukuja, ne järjestetään suuruusjärjestykseen. Jos taas listalla on merkkijonoja, ne järjestetään aakkosjärjestykseen.

Listan voi kääntää ympäri seuraavalla komennolla:

Collections.reverse(lista);

Listan järjestyksen voi sekoittaa seuraavalla komennolla:

Collections.shuffle(lista);

Esimerkki: Lottoarvonta

Seuraava ohjelma arpoo viikon lottonumerot eli 7 eri numeroa väliltä 1–39.

ArrayList<Integer> kaikki = new ArrayList<Integer>();

for (int i = 1; i <= 39; i++) {
    kaikki.add(i);
}

Collections.shuffle(kaikki);

ArrayList<Integer> oikeat = new ArrayList<Integer>();

for (int i = 0; i < 7; i++) {
    oikeat.add(kaikki.get(i));
}

Collections.sort(oikeat);

System.out.println("Lottonumerot:");
System.out.println(oikeat);

Ohjelman tulostus voi olla seuraava:

Lottonumerot:
[5, 7, 9, 14, 22, 26, 32]

Ohjelman toiminta on seuraava:

  1. Ohjelma lisää listalle kaikki mahdolliset lottonumerot väliltä 1–39.
  2. Ohjelma sekoittaa listan kaikki.
  3. Ohjelma lisää listan kaikki 7 ensimmäistä lottonumeroa listalle oikeat.
  4. Ohjelma järjestää listan oikeat.
  5. Ohjelma tulostaa listan oikeat.