-
Notifications
You must be signed in to change notification settings - Fork 0
Listat
Hyödynnä myös Helsingin yliopiston MOOC-kurssin materiaaleja: https://ohjelmointi-19.mooc.fi/osa-3/2-listat.
Listat ovat tietorakenteita, joiden pituus kasvaa joustavasti, kun niihin lisätään uusia arvoja. Listoihin voidaan lisätä arvoja myös aiempien arvojen väliin ja listan väleistä voidaan poistaa arvoja. Listat ovat olioita ja niillä on metodeita, joiden avulla arvoja lisätään, poistetaan, etsitään jne.
Yhdessä listassa voidaan varastoida ainoastaan yhdentyyppisiä arvoja, eikä varastoitavaa tyyppiä voida myöhemmin vaihtaa. Listoissa voidaan varastoida ainoastaan olioita, ei siis alkeistietotyyppejä kuten boolean
, int
ja double
. Alkeistietotyypit voidaan kuitenkin esittää myös olioina kääreluokkien Boolean
, Integer
ja Double
avulla.
Javassa on useita eri listatyyppejä. Kaikki listat toimivat ulkoisesti samalla tavalla, vaikka niiden sisäiset toteutustavat vaihtelevat merkittävästi. ArrayList
on sisäisesti toteutettu taulukon avulla, kun taas LinkedList
on toteutettu linkittämällä listan alkiot toisiinsa "ketjuksi". Sopivin lista kuhunkin tarkoitukseen vaihtelee listan käyttötavasta riippuen, mutta pääsääntöisesti pärjäät hyvin käyttämällä aina ArrayList
-listoja.
Listat sijaitsevat java.util
-paketissa, joten ne otetaan käyttöön esim. seuraavilla import
-käskyillä:
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
Voit luoda itsellesi merkkijonolistoja seuraavasti:
ArrayList<String> taulukkoLista = new ArrayList<String>();
LinkedList<String> linkitettyLista = new LinkedList<String>();
Listat ovat geneerisiä, eli niiden sisällön tyyppi voidaan määritellä itse. Edellä määritellyt listat säilyttävät merkkijonoja ja tämä ArrayList
voi säilyttää kokonaislukuja:
// kulmasuluissa oleva tyypin nimi kertoo, mitä arvoja listalla säilytetään:
ArrayList<Integer> numerot2 = new ArrayList<Integer>();
Java osaa päätellä luotavan listan tyypin muuttujan tyypistä, joten voimme määritellä listan luonnissa tyypin tyhjäksi <>
. Java päättelee tyypiksi <String>
:
// jälkimmäiset kulmasulut voidaan jättää tyhjiksi:
ArrayList<String> merkkijonot = new ArrayList<>();
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class Listaluokat {
public static void main(String[] args) {
// Javassa on useita eri listatyyppejä:
ArrayList<String> taulukkoLista = new ArrayList<String>();
LinkedList<String> linkitettyLista = new LinkedList<String>();
// Listat ovat geneerisiä, eli niiden sisällön tyyppi voidaan määritellä itse.
// Edellä määritellyt listat säilyttävät merkkijonoja ja tämä ArrayList voi
// säilyttää kokonaislukuja:
ArrayList<Integer> numerot2 = new ArrayList<Integer>();
// Java osaa päätellä luotavan listan tyypin muuttujan tyypistä, joten
// voimme määritellä listan luonnissa tyypin tyhjäksi '<>' -> '<String>'
ArrayList<String> merkkijonot = new ArrayList<>();
// Kaikki listatyypit ovat yhteensopivia "List"-tyypin kanssa, joten muuttujan
// tyypiksi voidaan määritellä yleisesti List:
List<String> yleinenMerkkijonoLista = new ArrayList<>();
// Tällä kurssilla tulemme käyttämään lähinnä ArrayList-listoja!
}
}
Listoja käytetään aina kutsumalla listan metodeja:
add
-metodi lisää listalle uusia arvoja listan loppuun:
List<String> sanat = new ArrayList<>();
sanat.add("Hello");
sanat.add("World");
System.out.println(sanat); // [Hello, World]
Listalle voidaan lisätä myös arvoja tiettyyn indeksiin. Tällöin add
-metodille annetaan ensimmäiseksi parametriarvoksi haluttu indeksi. Seuraavien listalla olevien arvojen indeksit kasvavat yhdellä:
List<String> sanat = new ArrayList<>();
// lisätään arvoja listan loppuun:
sanat.add("Hello");
sanat.add("World");
// lisätään arvoja tiettyyn indeksiin:
sanat.add(0, "Terve");
sanat.add(1, "Maailma");
System.out.println(sanat); // [Terve, Maailma, Hello, World]
List<String> sanat = new ArrayList<>();
sanat.add("Hello");
sanat.add("World");
System.out.println(sanat.size()); // 2
Listalta voidaan hakea yksittäisiä arvoja get
-metodin avulla. Huomaa, että listojen indeksit alkavat aina nollasta!
List<String> sanat = new ArrayList<>();
sanat.add("Hello");
sanat.add("World");
System.out.println(sanat.get(0)); // Hello
System.out.println(sanat.get(1)); // World
Listalta voidaan poistaa joko tietyn indeksin perusteella tai tiettyjä arvoja remove
-metodin avulla. Huomaa, että listojen indeksit alkavat aina nollasta!
List<String> sanat = new ArrayList<>();
sanat.add("Hello");
sanat.add("World");
sanat.add("!");
// poistetaan indeksin perusteella:
sanat.remove(0);
// poistetaan tietty arvo:
sanat.remove("World");
System.out.println(sanat); // [!]
Listoilta voidaan etsiä alkioita kahdella metodilla:
-
contains
palauttaatrue
, jos annettu arvo löytyy jostain kohtaa listalta -
indexOf
palauttaa sen indeksin, josta annettu arvo löytyy - Huom! Listojen indeksit alkavat aina nollasta
- Huom! Jos annettua arvoa ei löydy,
indexOf
palauttaa luvun-1
ArrayList<String> nimet = new ArrayList<>();
nimet.add("Matti");
nimet.add("Maija");
System.out.println(nimet.contains("Matti")); // true
System.out.println(nimet.indexOf("Maija")); // 1
System.out.println(nimet.indexOf("Maikki")); // -1, eli ei löydy!
- Listan sisältö on usein tarpeellista käydä läpi alusta loppuun
- Tämä voidaan toteuttaa toistorakenteella, jossa lähdetään liikkeelle nollasta ja edetään viimeiseen indeksiin
sanat.size() – 1
- Toistorakenteen sisällä saadaan kulloinkin käsiteltävä arvo pyydettyä listalta käyttäen toistomuuttujaa:
get(i)
import java.util.ArrayList;
import java.util.List;
public class ListanLapikayntiFor {
public static void main(String[] args) {
List<Integer> numerot = new ArrayList<>();
numerot.add(321);
numerot.add(456);
numerot.add(789);
// käydään kaikki listan arvot läpi:
for (int i = 0; i < numerot.size(); i++) {
System.out.println(numerot.get(i));
}
}
}
Katso esim: https://stackoverflow.com/a/22114571
For-each –silmukalla on mahdollista käydä kätevästi kaikki tietyn listan arvot läpi ilman, että pidämme itse kirjaa indeksistä ja haemme arvoja get
-metodilla:
import java.util.ArrayList;
import java.util.List;
public class ListanLapikayntiForEach {
public static void main(String[] args) {
List<Integer> numerot = new ArrayList<>();
numerot.add(321);
numerot.add(456);
numerot.add(789);
// käydään kaikki listan arvot läpi:
for (Integer arvo : numerot) {
System.out.println(arvo);
}
}
}
Kaikki listatyypit ovat yhteensopivia List
-tyypin kanssa, joten muuttujan tyypiksi voidaan määritellä yleisesti List
:
// List<String> -muuttujaan voidaan sijoittaa esim. LinkedList- ja ArrayList-listoja:
List<String> merkkijonoLista = new ArrayList<>();
Muista, että tarvitset sekä List
-tyypille että ArrayList-tyypille import-komennot luokan alkuun:
import java.util.ArrayList;
import java.util.List;
Jos muuttujan tyypiksi määriteltäisiin tarkasti ArrayList<String>
, voisimme asettaa muuttujaan ainoastaan ArrayList
-tyyppisen listan. Tällöin emme voisi käyttää esim. List.of
-luontitapaa valmiin listan luomiseksi:
// VIRHE: Type mismatch: cannot convert from List<String> to ArrayList<String>
ArrayList<String> lista = List.of("sana", "toinen");
// Toimii, koska List<String> on yhteensopiva kaikkien merkkijonolistojen kanssa:
List<String> lista = List.of("sana", "toinen");
Lista on mahdollista järjestää helposti alkioiden "luonnolliseen järjestykseen". Collections
-apuluokalla on olemassa sort
-niminen metodi, joka järjestää sille annetun listan:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class KaupunkienSorttaus {
public static void main(String[] args) {
List<String> kaupungit = new ArrayList<>();
kaupungit.add("Rauma");
kaupungit.add("Helsinki");
kaupungit.add("Espoo");
kaupungit.add("Vantaa");
kaupungit.add("Turku");
// Tulostaa siinä järjestyksessä, kun lisäsimme arvot:
System.out.println(kaupungit); // [Rauma, Helsinki, Espoo, Vantaa, Turku]
Collections.sort(kaupungit); // järjestää "luonnolliseen" järjestykseen
// Lista on nyt eri järjestyksessä:
System.out.println(kaupungit); // [Espoo, Helsinki, Rauma, Turku, Vantaa]
}
}
Huomaa, että merkkijonojen luonnollinen järjestys ei toimi odotetusti eri kokoisia kirjaimia vertaillessa.
List<String> lista = new ArrayList<String>();
lista.add("Terve");
lista.add("Maailma");
// Tapa 1: annetaan kopioitava lista parametrina luotaessa uutta ArrayList:iä
List<String> kopio1 = new ArrayList<>(lista);
// Tapa 2: lisätään kaikki alkiot tyhjään listaan kutsumalla addAll-metodia
List<String> kopio2 = new ArrayList<>();
kopio2.addAll(lista);
Tämän oppimateriaalin on kehittänyt Teemu Havulinna ja se on lisensoitu Creative Commons BY-NC-SA -lisenssillä.