Luku esittelee taulukoiden idean, määrittelyn ja käytön. Myös matriiseihin tutustutaan. Taulukoiden käsittelyn perusalgoritmeihin perehdytään: etsiminen ja järjestäminen tulevat tutuiksi. Luvun lopussa nähdään, miten taulukon elementit voivat olla mitä vain Javan olioita.
Olkoon ohjelmointitehtävänä tulostaa 100 syöttölukua käänteisessä järjestyksessä. Ainoa mahdollisuus ratkaista ongelma jo opitulla kalustolla on:
private static Scanner lukija = new Scanner(System.in); ... int luku1, luku2, ....... // nuo pisteet eivät valitettavasti ole Javaa! luku99, luku100; // luetaan 100 lukua: System.out.println("Anna luku 1"); luku1 = lukija.nextInt(); System.out.println("Anna luku 2"); luku2 = lukija.nextInt(); ....... // nuo pisteet eivät valitettavasti ole Javaa! System.out.println("Anna luku 100"); luku100 = lukija.nextInt(); // tulostetaan luvut käänteisessä järjestyksessä: System.out.println("Luvut lopusta alkuun:"); System.out.println(luku100); System.out.println(luku99); ....... // nuo pisteet eivät valitettavasti ole Javaa! System.out.println(luku2); System.out.println(luku1);Kovin kävisi työlääksi ohjelman laatiminen tuohon tapaan! Jokaista muuttujaa luku1, luku2, ..., luku100 käsitellään ihan samaan tapaan ja kuitenkin joudutaan kirjoittamaan kaikki käsittelyt erikseen!
Taulukon idea on, että yksi muuttujan nimi voi tarkoittaa kokonaista jonoa keskenään samantyyppisiä muuttujia. Kutakin tuollaista "alimuuttujaa" kutsutaan taulukon alkioksi eli komponentiksi. Yksittäisiin "alimuuttujiin" viitatataan indeksoimalla taulukkomuuttujaa:
Jos vaikkapa luku on tuollainen taulukkomuuttuja, ilmaus
luku[7]tarkoittaa muuttujan luku "alimuuttujaa", jonka indeksi on 7. Tuota "alimuuttujaa" voidaan käsitellä ihan samaan tapaan kuin mitä tahansa samantyyppistä tavallista muuttujaa. Jos siis taulukkomuuttujan luku alkiotyyppi on int, voidaan kirjoittaa:
luku[7] = 56; luku[7] += 3; luku[7] = luku[7]*luku[7]; ++luku[7]; luku[7] = lukija.nextInt(); System.out.println(luku[7]); jne, jne ....
Ja nyt edellinen esimerkki voidaan ohjelmoida:
int[] luku = new int[101]; // Tämä selviää pian! // luetaan 100 lukua: for (int i=1; i<=100; ++i) { System.out.println("Anna luku "+i); luku[i] = lukija.nextInt(); } // tulostetaan luvut käänteisessä järjestyksessä: System.out.println("Luvut lopusta alkuun:"); for (int i=100; i>=1; --i) System.out.println(luku[i]);Näin siis samalla ilmauksella
luku[i]tarkoitetaan i:n arvosta riippuen milloin mitäkin int-muuttujista
luku[1], luku[2], ... luku[99], luku[100].Huom: Indeksilauseke voi toki olla muutakin kuin pelkkä vakio tai muuttuja:
luku[7+j] = luku[i-3] * luku[i*i];
int[] luku = new int[101];
int luku[] = new int[101];Onneton menettely on kotoisin eräistä Javan edeltäjistä. Koska edellinen tapa on paljon selkeämpi, kurssilla käytetään ainoastaan sitä!]
Taulukot ovat siis Javassa olioita: Ne luodaan konstruktorilla, niitä käsitellään viitteinä, ..., parametrina välitettyä taulukkoa voi muuttaa, metodi voi palauttaa arvonaan viitteen taulukkoon, ...
Sääntöjä:
import java.util.Scanner; public class KaannaLuvut { private static Scanner lukija = new Scanner(System.in); public static void main(String[] args) { int[] luku = new int[100]; // luetaan 100 lukua: for (int i=0; i < luku.length; ++i) { System.out.println("Anna luku "+(i+1)); luku[i] = lukija.nextInt(); } // tulostetaan luvut käänteisessä järjestyksessä: System.out.println("Luvut lopusta alkuun:"); for (int i=luku.length-1; i >= 0; --i) System.out.println(luku[i]); } }
Taulukon alkioiden läpikäynti on aina syytä tehdä yleisellä tavalla
for (int i=0; i < luku.length; ++i) ...Näin ohjelmaa ei tarvitse muuttaa, jos taulukon kokoa halutaan muuttaa tai vaikkapa tehdä ohjelmasta yleisempi versio; taulukko-olio voidaan luoda myös kysytyn kokoiseksi (KaannaLuvut2.java):
import java.util.Scanner; public class KaannaLuvut2 { private static Scanner lukija = new Scanner(System.in); public static void main(String[] args) { int lukumäärä; do { System.out.println("Montako lukua käännetään? (Vähintään yksi!)"); lukumäärä = lukija.nextInt(); } while (lukumäärä < 1); int[] luku = new int[lukumäärä]; // Huom: muuttuja! // Loppuosa ohjelmasta säilyy aivan ennallaan! for (int i=0; i < luku.length; ++i) { System.out.println("Anna luku "+(i+1)); luku[i] = lukija.nextInt(); } // tulostetaan luvut käänteisessä järjestyksessä: System.out.println("Luvut lopusta alkuun:"); for (int i=luku.length-1; i >= 0; --i) System.out.println(luku[i]); } }Javan versio 1.5 toi mukanaan uuden tavan käydä läpi taulukon kaikki alkiot ilman tarvetta indeksoida itse, "omin käsin". For-lauseen uusi syntaksivaihtoehto on
for (alkio : taulukko) käsittele alkio;Lause tarkoittaa sitä, että yksi kerrallaan käydään läpi kaikki taulukon alkiot ja toistettava alialgoritmi saa yksitellen käyttöönsä kaikkien niiden arvot muuttujassa alkio. Toistettavalla alialgoritmilla ei ole mitään tietoa alkion indeksistä, vain arvosta. Alialgoritmi ei myöskään pääse muuttamaan taulukon alkioiden arvoja! Kuten arvata saattaa, tämä muoto for-lauseesta soveltuu juuri tilanteisiin, joissa mitään tietoa alkion indeksistä ei tarvita!
Tällaisella semantiikalla varustettua for-toistoa kutsutaan joissakin ohjelmointikielissä for-each-toistoksi ilmeisestä syystä. Javassa tällainen on käytettävissä talukon kaikkien alkioiden läpikäynnin lisäksi myös ns. kokoelmatyypeille (Collections). Uusi for-lause käy niissäkin yksitellen läpi kaikki tietorakenteen alkiot.
Esimerkki: Ohjelmoidaan metodi, joka laskee int-taulukon alkioiden summan ja palauttaa sen arvonaan. Summaa laskettaessa ei ole kiinnostavaa, missä järjestyksessä lasketaan eikä ole kiinnostavaa, mikä kunkin alkion indeksi on. Tämä on siis varsin oivallinen tilanne kayttää for-each-toistoa! (LaskeSumma.java)
private static int alkiodenSumma(int[] taulukko) { int summa = 0; for (int alkio : taulukko) summa = summa + alkio; return summa; }
Seuraava ohjelma antaa esimerkkejä monenlaisista taulukkomuuttujien määrittelyistä, taulukko-olioiden konstruoinnista ja taulukoiden käytöstä:
public class Tauluesimerkkeja { public static void main(String[] args) { // int-taulukoita: int[] kA; // taulukkomuuttuja, EI vielä taulukkoa! int[] kB = new int[10]; int[] kC = {5, -23, 12, 31, 7}; // tämä ilmaus konstruoi taulukon int[5] // ja asettaa alkioille alkuarvot!! // Näitä voi käyttää VAIN muuttujia // määriteltäessä! for (int i=0; i<kB.length; ++i) // 7:n kertotaulu kB[i] = 7*(i+1); for (int i=0; i<kB.length; ++i) System.out.println(kB[i]); kA = kC; // KOPIOIDAAN VIITE kA[1] = 123456; // MYÖS kC[1] MUUTTUU! System.out.println(kA[1] + " " + kC[1]); kC = new int[5]; // luodaan uusi taulukko kC:n arvoksi kC[1] = -98; System.out.println(kA[1] + " " + kC[1]); // double-taulukoita: double[] dA = new double[5]; double[] dB = {3.14, 7.21, 0.0, 9.1}; // double[4]! dA[2] = dB[0] + dB[3]; // boolean-taulukoita: boolean[] tA = new boolean[8]; boolean[] tB = {true, true, false}; // boolean[3]! tA[1] = tB[0] || tB[2]; if (tA[1]) System.out.println("Tosi on!"); // char-taulukoita: char[] mA = new char[10]; char[] mB = {'q', 'w', 'e'}; // char[3]! mB[1] = 'u'; System.out.println("Merkkialkion oletusalkuarvo on" + mA[2] + "."); // String-taulukoita: String[] jA = new String[3]; String[] jB = {"kissa", "hiiri"}; // String[2]! jA[0] = jB[1]; jA[2] = jB[0]; jA[1] = "koira"; for (String alkio : jA) System.out.println(alkio); jB[1] = jA[1]; } }Ohjelma tulostaa;
7 14 21 28 35 42 49 56 63 70 123456 123456 123456 -98 Tosi on! Merkkialkion oletusalkuarvo on. hiiri koira kissa
--------------- | 5 2 -3 | | 9 -1 4 | ---------------Tässä matriisissa on kaksi riviä ja kolme saraketta.
Toisinaan matriisia kutsutaan myös kaksiulotteiseksi taulukoksi. Myös esimerkiksi kolmiulotteinen taulukko on mahdollinen, samoin neliulotteinen...
Javassa oikeastaan ei ole kaksiuluotteisia taulukoita, mutta koska Javan taulukoiden komponenttityyppi voi olla mikä tahansa Javan tyyppi, myös taulukkotyyppi voi olla taulukon komponenttina! Näin saadaan luotua rakenteita jotka muistuttavat moniulotteisia taulukoita. Tässä luvussa tutustutaan vain "kaksiulotteisiin" taulukoihin, matriiseihin. Ja niitä kutsutaan jatkossa kaksiulotteisiksi ilman sitaatteja.
Määrittely
int[][] matriisiA;tarkoittaa, että muuttujan matriisiA tyyppi on int[]-taulukoista muodostuva taulukko.
Määrittely
int[][] matriisiA = new int[2][3];asettaa muuttujan alkuarvoksi 2*3 matriisin, jonka alkioiden alkuarvo on 0.
Määrittely
int[][] matriisiB = { {5, 2, -3}, {9, -1, 4} };puolestaan luo muuttujan matriisiB arvoksi 2*3 matriisin annetuin alkuarvoin.
Myös kaksiulotteisen taulukon alkioihin viitataan indeksoiden:
matriisiB[0]tarkoittaa int[]-taulukkoa
{5, 2, -3}Ilmaus
matriisiB[0][1]puolestaan tarkoittaa int-alkiota, jonka arvo on 2.
Kaksiulotteisen taulukon alkiot voidaan läpikäydä vaikkapa lauseella:
for (int rivi=0; rivi<matriisi.length; ++rivi) for (int sarake=0; sarake<matriisi[rivi].length; ++sarake) // alialgoritmi alkion matriisi[rivi][sarake] käsittelyynJos toistettavassa alialgoritmissa ei tarvita tietoa alkioiden indekseistä (riveistä ja sarakkeista) eikä käsittelyjärjestyksestä, läpikäynti voidaan ohjelmoida käyttäen for-each-toistoa:
for (int[] rivi : matriisi) for (int alkio : rivi) // alialgoritmi yhden alkion käsittelyyn
Laaditaan esimerkkisovellus, joka lukee 2*3-matriisin ja tulostaa sen 7:llä kerrottuna (so. jokainen alkio kerrotaan 7:llä). Lopuksi ohjelma laskee ja tulostaa "7:llä kerrotun" matriisin alkioiden summan. (Matriisi7.java).
import java.util.Scanner; public class Matriisi7 { private static Scanner lukija = new Scanner(System.in); public static void main(String[] args) { int[][] matriisi = new int[2][3]; // luetaan arvot: for (int rivi=0; rivi<matriisi.length; ++rivi) for (int sarake=0; sarake<matriisi[rivi].length; ++sarake) { System.out.println("Anna alkio "+rivi+", "+sarake); matriisi[rivi][sarake] = lukija.nextInt(); } // kerrotaan alkiot 7:llä: for (int rivi=0; rivi<matriisi.length; ++rivi) for (int sarake=0; sarake<matriisi[rivi].length; ++sarake) matriisi[rivi][sarake] *= 7; // operaatio '*='kertoo! // tulostetaan matriisi: System.out.println("Seitsemällä kerrottuna:"); for (int rivi=0; rivi<matriisi.length; ++rivi) { for (int sarake=0; sarake<matriisi[rivi].length; ++sarake) System.out.print(matriisi[rivi][sarake]+"\t"); System.out.println(); } // lasketaan alkioiden summa: int summa = 0; for (int[] rivi : matriisi) // nyt tarvitaan vain alkioiden arvot! for (int alkio : rivi) summa = summa + alkio; System.out.println("Alkioiden summa on " + summa + "."); } }
Laaditaan metodi, joka saa parametrinaan int[]-tyyppisen arvon eli kokonaislukutaulukon ja selvittää, löytyykö taulukosta toisena parametrina annettua kokonaislukua. Jos kysytty arvo löytyy, metodi palauttaa haettavan luvun indeksin arvonaan (jos haettavia on taulukossa monia, palautetaan niistä ensimmäisen indeksi). Jos kysyttyä ei löydy, metodin arvo on -1 (Hae.java):
public class Hae { // Peräkkäishaku int-taulukosta private static int hae(int[] taulu, int haettava) { for (int i=0; i<taulu.length; ++i) if (taulu[i] == haettava) return i; // tärppäsi, lopetetaan samantien return -1; // päästiin loppuun eikä löytynyt } public static void main(String[] args) { // testipääohjelma int[] a = {40, 20, 50, 10, 30}; System.out.println(hae(a, 10)); System.out.println(hae(a, 20)); System.out.println(hae(a, 30)); System.out.println(hae(a, 40)); System.out.println(hae(a, 50)); System.out.println(hae(a, 60)); } }Testiohjelma tulostaa:
3 1 4 0 2 -1
Jos taulukko on järjestyksessä, ns. binäärihaku on erittäin tehokas väline arvon hakemiseen taulukosta (BinHae.java):
public class BinHae { // Binäärihaku järjestetystä // int-taulukosta private static int binHae(int[] taulu, int haettava) { int vasen = 0; int oikea = taulu.length-1; int keski; while (vasen <= oikea) { keski = (vasen+oikea)/2; if (haettava == taulu[keski]) return keski; // löytyi ja lopetetaan! if (haettava < taulu[keski]) oikea = keski-1; else vasen = keski+1; } return -1; // hakualue tuli tyhjäksi eikä löytynyt } public static void main(String[] args) { // testipääohjelma int[] a = {10, 20, 30, 40, 50}; System.out.println(binHae(a, 5)); System.out.println(binHae(a, 10)); System.out.println(binHae(a, 20)); System.out.println(binHae(a, 30)); System.out.println(binHae(a, 35)); System.out.println(binHae(a, 40)); System.out.println(binHae(a, 50)); System.out.println(binHae(a, 60)); } }Tulostus:
-1 0 1 2 -1 3 4 -1
Yksi tehoton, mutta helposti ymmärrettävä järjestämisalgoritmi on ns. yksinkertainen vaihtojärjestäminen (nousevaan järjestykseen) (VaihtoJarj.java):
public class VaihtoJarj { // Yksinkertainen vaihtojärjestäminen private static void vaihtoJarjesta(int[] taulu) { for (int i=0; i < taulu.length-1; ++i) for (int j=i+1; j < taulu.length; ++j) if (taulu[i] > taulu[j]) { // onko järjestys väärä? int apu = taulu[i]; taulu[i] = taulu[j]; taulu[j] = apu; } } public static void main(String[] args) { // testipääohjelma int[] a = {40, 20, 50, 10, 30}; for (int i=0; i<a.length; ++i) System.out.print(a[i]+" "); System.out.println(); vaihtoJarjesta(a); for (int i=0; i<a.length; ++i) System.out.print(a[i]+" "); System.out.println(); // arvotaan taulukko: int[] b = new int[18]; for (int i=0; i<b.length; ++i) b[i] = (int)(300*Math.random()); for (int i=0; i<b.length; ++i) System.out.print(b[i]+" "); System.out.println(); vaihtoJarjesta(b); for (int i=0; i<b.length; ++i) System.out.print(b[i]+" "); System.out.println(); } }Tulostus (esimerkiksi):
40 20 50 10 30 10 20 30 40 50 234 49 212 257 273 219 289 104 81 129 158 247 133 161 205 72 229 54 49 54 72 81 104 129 133 158 161 205 212 219 229 234 247 257 273 289Yksinkertaisen vaihtojärjestämisen (vaikkapa nousevaan järjestykseen) idea on seuraava:
private static void kuplaJarjesta(int[] taulu) { for (int i=taulu.length; i > 0; --i) for (int j=0; j < i-1; ++j) if (taulu[j] > taulu[j+1]) { // onko järjestys väärä? int apu = taulu[j]; taulu[j] = taulu[j+1]; taulu[j+1] = apu; } }Edellisiä hieman parempi järjestämisalgoritmi on ns. lisäysjärjestäminen (insertion sort) (LisaysJarj.java):
private static void lisaysJarjesta(int[] taulu) { for (int i=1; i<taulu.length; ++i) { int apu = taulu[i]; int j = i; while (j > 0 && taulu[j-1] > apu) { taulu[j] = taulu[j-1]; --j; } taulu[j] = apu; } }
Järjestämisalgoritmien (kuten muidenkin algoritmien!) tehokkuutta voidaan analysoida matemaattisesti: kaikki edelläesitetyt järjestämisalgoritmit kuuluvat ns. luokkaan O(n2). Se tarkoittaa suurinpiirtein, että "jos järjestettävän taulukon koko kaksinkertaistetaan, algoritmin suoritusaika nelinkertaistuu". Parhaat ns. "yleiset" järjestämisalgoritmit "toimivat ajassa O(n*log n)".
Toisaalta suoritusaikoja voidaan myös kokeellisesti mitata. Pieni vertailu antaa seuraavia suoritusaikoja kun järjestetään 50000-alkoinen int-taulukko (ohjelma VertaileJarjAlgoritmeja.java) (Ajat riippuvat tietysti käytettävästä tietokoneesta, mutta suhteet säilynevät. Esimerkin ajat ovat millisekunteina.):
arvottu valmiiksi käänteisessä alkujärjestys järjestetty järj. oleva taulukko taulukko vaihtojärj. 4908 4678 8584 kuplajärj. 9846 4849 8236 lisäysjärj. 2777 3 5560Kuten taulukosta näkee, lisäysjärjestäminen on muita paljon nopeampi vaikka se kuuluukin niiden kanssa samaan "tehokkuusluokkaan". Ja erityisesti melkein järjestyksessä olevien taulukoiden järjestämisessä se on ylivoimainen.
Myös taulukon komponentit voivat olla olioita eli tarkemmin sanottuna viitteitä olioihin!
String-olioita sisältävä taulukkomuuttuja voidaan määritellä:
String[] taulu;Metodin muuttujana taululla ei ole mitään alkuarvoa, luokassa määriteltynä sillä on alkuarvo null.
Erityisesti on siis syytä huomata, että määrittely String[] taulu; EI siis luo taulukko-oliota, se vain nimeää muuttujan, joka voidaan asettaa viittaamaan taulukko-olioon. Taulukko-olio on siis luotava erikseen:
String[] taulu = new String[5];asettaa muuttujan taulu alkuarvoksi viisialkioisen String-taulukko-olion. Ja tässä on syytä huomata erityisesti, että määrittely new String[5] luo taulukko-olion, jonka alkioilla EI ole arvonaan vielä mitään String-olioita. String-taulukon alkioilla on vain oletusalkuarvo null, viite "ei mihinkään olioon"!
Lause
String[] taulu = {"kissa", "hiiri", "koira"};asettaa muuttujan taulu alkuarvoksi kolmialkioisen String-taulukko-olion, jonka alkioilla on luetellut alkuarvot.
Huom: Pääohjelmametodin pakollinen parametri
String[] argson siis String-taulukko. Sen alkuarvoksi tulevat automaattisesti ohjelman käynnistyskomentoa seuraavat välilyönnein toisistaan erotetut merkkijonot, ns. komentoriviparametrit. Jos ohjelma Ohjelma käynnistetään komennolla
java Ohjelma apina ja gorillapääohjelman args-parametri saa alkuarvokseen kolmialkioisen String-taulukon, jonka alkioilla on arvot "apina", "ja" ja "gorilla".
Esimerkkejä String-taulukoista (STauluKoe.java):
public class STauluKoe { // apuväline taulukon tulostamiseen: private static void tulostaSTaulu(String[] taulu) { System.out.println("\n ---- taulukon koko: "+taulu.length+":"); for (String alkio : taulu) // (for-each!) System.out.println(alkio); } public static void main(String[] args) { tulostaSTaulu(args); // komentoriviparametrit String[] ekaTaulu, tokaTaulu = new String[5], kolmasTaulu = {"kissa", "hiiri", "koira"}; tulostaSTaulu(kolmasTaulu); tulostaSTaulu(tokaTaulu); // null-alkuarvot for (int i=0; i<tokaTaulu.length; ++i) tokaTaulu[i] = "(" + i + ")"; tulostaSTaulu(tokaTaulu); // tulostaSTaulu(ekaTaulu); OLISI TÄSSÄ VIRHEELLINEN! ekaTaulu = kolmasTaulu; // kopioidaan viite! tulostaSTaulu(ekaTaulu); ekaTaulu = tokaTaulu; tulostaSTaulu(ekaTaulu); ekaTaulu[1] = args[2]; tulostaSTaulu(ekaTaulu); if (args.length > 2) { ekaTaulu[1] = args[2]; ekaTaulu[3] = args[0]; tulostaSTaulu(ekaTaulu); } } }Kun ohjelma käynnistetään komennolla:
java STauluKoe apina ja gorillasaadaan tulostus:
---- taulukon koko: 3: apina ja gorilla ---- taulukon koko: 3: kissa hiiri koira ---- taulukon koko: 5: null null null null null ---- taulukon koko: 5: (0) (1) (2) (3) (4) ---- taulukon koko: 3: kissa hiiri koira ---- taulukon koko: 5: (0) (1) (2) (3) (4) ---- taulukon koko: 5: (0) gorilla (2) apina (4)
Varsinaiseen "merkkipeliin" luokat StringBuilder ja StringBuffer ovat käyttökelpoisempia. Tällä kurssilla noita luokkia ei kuitenkaan opetella. Tietoa niistä löytyy Javan API-kuvaksesta: StringBuilder, StringBuffer.
Koska on kuitenkin hyödyllistä oppia tekemään asiat "omin käsin", tällä kurssilla tutustutaan merkkitaulukon käyttämiseen merkkijonojen käsittelyssä:
Määrittelyt
char[] jono1 = new char[10]; char[] jono2 = {'k','i','s','s','a'};asettavat muuttujan jono1 arvoksi 10-alkioisen merkkitaulukon ja muuttujan jono2 arvoksi 5-alkioisen merkkitaulukon. Jälkimmäisen alkioille annetaan alkuarvot, edellisen alkiot saavat oletusalkuarvon (merkkityypin oletusalkuarvo taulukossa ja luokan kenttänä on ns. null-merkki '\u0000').
Nyt voidaan ohjelmoida vaikkapa:
for (char alkio : jono2) // for-each! System.out.print(alkio); System.out.println(); for (int i=0; i<jono1.length; ++i) jono1[i] = '*'; for (int i=0; i<jono2.length; ++i) jono1[9-i] = jono2[i]; for (char alkio : jono1) // for-each! System.out.print(alkio); System.out.println();Lauseet tulostavat:
kissa *****assikString-olioita voi muuntaa char[]-taulukoiksi String-luokan metodilla:
import java.util.Scanner; public class Aeta { private static Scanner lukija = new Scanner(System.in); public static void main(String[] args) { System.out.println("Anna merkkijono"); String jono = lukija.nextLine(); char[] mtaulu = jono.toCharArray(); for (int i=0; i<mtaulu.length; ++i) if (mtaulu[i] == 'a') mtaulu[i] = 'ä'; else if (mtaulu[i] == 'A') mtaulu[i] = 'Ä'; jono = new String(mtaulu); System.out.println("Merkkijono muunnettuna:"); System.out.println(jono); } }Huom: Merkkijonotaulukko (char[]-olio) on mahdollista tulostaa sellaisenaankin (koska println-metodi on kuormitettu!):
System.out.println(mtaulu);
Pikkuvarasto[] varastot = new Pikkuvarasto[4];määrittelee Pikkuvarasto[]-tyyppisen muuttujan ja asettaa sen alkuarvoksi neljästä Pikkuvarasto-tyyppisestä muuttujasta muodostuvan taulukon. Taulukon alkioiden alkuarvo on null. Toisin sanoen: nelialkionen taulukko-olio luodaan ja sijoitetaan muuttujan varastot arvoksi, mutta taulukon alkioiden arvona ei vielä ole Pikkuvarasto-olioita! Niitä voidaan sitten luoda erikseen:
varastot[0] = new Pikkuvarasto(10, "Mehu"); varastot[1] = new Pikkuvarasto(123.4, "Olut"); ...Tämän jälkeen taulukon alkioita - noita luotuja Pikkuvarasto-olioita - voidaan käyttää aivan samaan tapaan kuin aiemmin:
varastot[0].vieVarastoon(30.0); System.out.println(varastot[0].paljonkoOn()); varastot[0].otaVarastosta(7.0); System.out.println(varastot[0]); varastot[2] = varastot[0]; System.out.println(varastot[2].mikäNimi());
Toteutetaan luokka AlaspainLaskureita, sadasta alaspäin laskevien laskureiden toteutukseksi:
public class AlaspainLaskureita { // tietorakenne: private int[] laskurit; // konstruktori: public AlaspainLaskureita(int kpl) { if (kpl<=1) laskurit = new int[1]; else laskurit = new int[kpl]; for (int i=0; i<laskurit.length; ++i) laskurit[i] = 100; } public int seuraava(int n) { if (n<0 || n>=laskurit.length) return -1; int arvo = laskurit[n]; if (laskurit[n]>0) --laskurit[n]; return arvo; } // testipääohjelma: public static void main(String[] args) { AlaspainLaskureita a = new AlaspainLaskureita(10); AlaspainLaskureita b = new AlaspainLaskureita(-10); // vähentyminen: System.out.println(a.seuraava(3)); System.out.println(a.seuraava(3)); System.out.println(a.seuraava(3)); // virheellinen alkio: System.out.println(a.seuraava(12)); // loppuuko väheneminen: for (int i=0; i<98; ++i) { int apu = a.seuraava(7); } System.out.println(a.seuraava(7)); System.out.println(a.seuraava(7)); System.out.println(a.seuraava(7)); System.out.println(a.seuraava(7)); // tuliko yhden mittaiseksi väärästä konstruoinnista: System.out.println(b.seuraava(0)); System.out.println(b.seuraava(0)); System.out.println(b.seuraava(1)); } }Testipääohjelma tulostaa:
100 99 98 -1 2 1 0 0 100 99 -1