Listat ja viitteet
Tarkastellaan vielä olioiden — tai viittaustyyppisten muuttujien — käyttöä listalla. Kun olio lisätään listalle, listalle kopioidaan viite. Kuten aiemmin, olion sisäisestä tilasta ei luoda kopiota, vaan listalle lisätään viite olemassa olevaan olioon.
Alla olevassa esimerkissä luodaan ensin olio juhana
, joka lisätään listalle. Tämän jälkeen listalle lisätään kaksi muuta oliota. Seuraavaksi juhana
-olion metodia vanhene
kutsutaan. Lopulta jokaista listalla olevaa oliota vanhennetaan.
ArrayList<Henkilo> henkilot = new ArrayList<>();
Henkilo juhana = new Henkilo("Juhana");
henkilot.add(juhana);
henkilot.add(new Henkilo("Matti"));
henkilot.add(new Henkilo("Martin"));
// juhana vanhenee 2 vuotta
juhana.vanhene();
juhana.vanhene();
for (Henkilo henkilo: henkilot) {
henkilo.vanhene();
}
for (Henkilo henkilo: henkilot) {
System.out.println(henkilo);
}
Juhana, ikä 3 vuotta Matti, ikä 1 vuotta Martin, ikä 1 vuotta
Listalle on kopioituna viitteet olioihin. Yllä olevassa esimerkissä muuttujan juhana
arvona on sama viite kuin listalla, joten "Juhanan" ikä muuttuu myös jos hän vanhenee listan ulkopuolella.

Lista oliomuuttujana
Listat ovat olioita, joten oliomuuttujaksi voi asettaa listan. Tarkastellaan tätä seuraavaksi.
Olemme aiemmin huomanneet, että listat ovat näppäriä muunmuassa silloin, kun haluamme pitää kirjaa useammasta erillisestä asiasta. Alla olevassa esimerkissä käsitteelle soittolista on luotu luokka. Soittolista sisältää kappaleita.
// 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();
Sorateiden kuningas Teuvo, maanteiden kuningas
Oliomuuttujana oleva lista voi sisältää merkkijonojen lisäksi myös muunlaisia olioita. Laajennetaan edellä hahmoteltua luokkaa PainonvartijaYhdistys
siten, että yhdistys lisää kaikki jäsenensä listalle. Laajennetussa versiossa konstruktorille annetaan alimman painoindeksin lisäksi myös luotavan yhdistyksen nimi:
public class PainonvartijaYhdistys {
private double alinPainoindeksi;
private String nimi;
private ArrayList<Henkilo> jasenet;
public PainonvartijaYhdistys(String nimi, double alinPainoindeksi) {
this.alinPainoindeksi = alinPainoindeksi;
this.nimi = nimi;
this.jasenet = new ArrayList<>();
}
//..
}
Tehdään metodi jolla henkilö liitetään yhdistykseen. Metodi ei liitä yhdistykseen kuin tarpeeksi suuren painoindeksin omaavat henkilöt. Tehdään myös toString jossa tulostetaan jäsenten nimet:
public class PainonvartijaYhdistys {
// ...
public boolean hyvaksytaanJaseneksi(Henkilo henkilo) {
if (henkilo.painoindeksi() < this.alinPainoindeksi) {
return false;
}
return true;
}
public void lisaaJaseneksi(Henkilo henkilo) {
// sama kuin hyvaksytaanJaseneksi(henkilo) == false
if (!hyvaksytaanJaseneksi(henkilo)) {
// void-tyyppisistä metodeista voi palata
// return-kutsulla
return;
}
this.jasenet.add(henkilo);
}
public String toString() {
String jasenetMerkkijonona = "";
for (Henkilo jasen: this.jasenet) {
jasenetMerkkijonona = jasenetMerkkijonona + " " + jasen.getNimi() + "\n";
}
return "Painonvartijayhdistys " + this.nimi + " jäsenet: \n" + jasenetMerkkijonona;
}
}
Metodi lisaaJaseneksi
käyttää aiemmin tehtyä metodia hyvaksytaanJaseneksi
.
Kokeillaan laajentunutta painonvartijayhdistystä:
PainonvartijaYhdistys painonVartija = new PainonvartijaYhdistys("Kumpulan paino", 25);
Henkilo matti = new Henkilo("Matti");
matti.setPaino(86);
matti.setPituus(180);
painonVartija.lisaaJaseneksi(matti);
Henkilo juhana = new Henkilo("Juhana");
juhana.setPaino(64);
juhana.setPituus(172);
painonVartija.lisaaJaseneksi(juhana);
Henkilo harri = new Henkilo("Harri");
harri.setPaino(104);
harri.setPituus(182);
painonVartija.lisaaJaseneksi(harri);
Henkilo petri = new Henkilo("Petri");
petri.setPaino(112);
petri.setPituus(173);
painonVartija.lisaaJaseneksi(petri);
System.out.println(painonVartija);
Tulostuksesta huomaamme, että Juhanaa ei kelpuutettu jäseneksi:
Tehdään vielä lopuksi painovartijayhdistykselle metodi, jolla saadaan tietoon yhdistyksen suurimman painoindeksin omaava henkilö.
public class PainonvartijaYhdistys {
// ...
public Henkilo suurinPainoindeksinen() {
// jos jasenlista on tyhjä, palautetaan null-viite
if (this.jasenet.isEmpty()) {
return null;
}
Henkilo painavinTahanAsti = this.jasenet.get(0);
int indeksi = 1;
while (indeksi < this.jasenet.size()) {
Henkilo henkilo = this.jasenet.get(indeksi);
if (henkilo.painoindeksi() > painavinTahanAsti.painoindeksi()) {
painavinTahanAsti = henkilo;
}
indeksi = indeksi + 1;
}
return painavinTahanAsti;
}
}
Logiikaltaan edeltävä metodi toimii samaan tapaan kuin suurimman luvun etsiminen taulukosta. Käytössä on apumuuttuja painavinTahanAsti
joka laitetaan aluksi viittaamaan listan ensimmäiseen henkilöön. Sen jälkeen käydään lista läpi ja katsotaan tuleeko vastaan suuremman painoindeksin omaavia henkilöitä, jos tulee, niin otetaan viite talteen muuttujaan painavinTahanAsti
. Lopuksi palautetaan muuttujan arvo eli viite henkilöolioon.
Tehdään lisäys edelliseen pääohjelmaan. Pääohjelma ottaa vastaan metodin palauttaman viitteen muuttujaan painavin
.
PainonvartijaYhdistys painonVartija = new PainonvartijaYhdistys("Kumpulan paino", 25);
// .. lisätään listalle ..
Henkilo painavin = painonVartija.suurinPainoindeksinen();
System.out.print("suurin painoindeksi on jäsenellä " + painavin.getNimi());
suurin painoindeksi on jäsenellä Petri
Muistathan tarkistaa pistetilanteesi materiaalin oikeassa alareunassa olevasta pallosta!