Luku esittelee luokat Vector ja Hashtable. Vector on vaihtelevan kokoinen taulukko, jonne voi tallettaa mitä tahansa Javan olioita. Hashtable on rakenne, jolla voi luoda ns. assosiaatiolistoja: olioon voidaan liittää jokin toinen olio ja ensimmäisellä assosioda toinen, esimerkiksi "avaimella voidaan hakea arvoa".
Molemmissa tietorakenteissa käsiteltävät oliot ovat mahdollisimman yleisiä, luokan Object ilmentymiä. Siksi tuollaisten käsittelystä on ensin opittava jotakin.
Luokassa Object on joitakin metodeita, jotka siis periytyvät kaikille muille luokille. Vanha tuttu on toString(), joka on tapana aliluokissa kuormittaa sopivasti. Object-luokan toString() muodostaa oliosta kuin oliosta tekstiesityksen, joka kertoo olion luokan ja heksadesimaaliluvun olion sijainnista suoritusaikaisessa ns. hajautustaulussa, esim. PikkuVarasto@80cb94a.
Object-tyyppiselle muuttujalle voi sijoittaa minkä tahansa olioarvon, mutta tällöin tuolle oliolle voi soveltaa vain Object-luokan metodeita. Jos näitä on polymorfisesti korvattu aliluokissa (ks. luku 4.4), valitaan kuitenkin olion oman luokan metodi.
Kun Object-tyyppisen muuttujan arvona on jonkin aliluokan ilmentymä ja tuolle oliolle halutaan soveltaa metodia, jota Object-luokasta ei löydy, olioarvo on muunnettava explisiittisellä tyyppimuunnoksella oman luokkansa tyyppiin, esim:
Object otus = new PikkuVarasto(); // ... otus.vieVarastoon(3.14); // väärin! ((PikkuVarasto)otus).vieVarastoon(3.14); // sallittu //... otus = "BÖÖ!"; int i; i = otus.length(); // väärin! i = ((String)otus).length(); // sallittuHuom: Komponenttiin viittaus (".") sitoo tiukemmin kuin eksplisiittinen tyyppimuunnos, siksi nuo sulkeet tyyppimuunnoksen ympärillä ovat välttämättömät, ks. "Operaatioiden sitovuus".
Olion luokkaa voi kysellä instanceof-operaatiolla:
Object otus = new PikkuVarasto(); // ... if (otus instanceof PikkuVarasto) ((PikkuVarasto)otus).vieVarastoon(3.14); else if (otus instanceof String) i = ((String)otus).length();
Joitakin Vector-luokan välineitä:
Esimerkki:
import java.util.*; public class VeEsim { public static void main(String[] args) { Vector taulu = new Vector(); int luku; System.out.println("Syötä lukuja, nolla lopettaa."); luku = Lue.kluku(); while (luku != 0) { taulu.addElement(new Integer(luku)); luku = Lue.kluku(); } System.out.println(taulu); System.out.println("Syötä poistettavia lukuja, nolla lopettaa."); luku = Lue.kluku(); while (luku != 0) { boolean oli = taulu.removeElement(new Integer(luku)); if (oli) System.out.println(taulu); else System.out.println("Ei löydy"); luku = Lue.kluku(); } System.out.println(taulu); System.out.println("Alkioiden summa = " + summa(taulu)); } private static int summa(Vector tau) { int summa = 0; for (int i=0; i < tau.size(); ++i) summa += ((Integer)(tau.elementAt(i))).intValue(); // tuo intValue() on siis luokassa Integer return summa; } }
Joku voisi ehkä sanoa, että Hashtable-olio on kuin taulukko, jota "indeksoidaan" olioilla ei kokonaisluvuilla..
Luokan Vector tapaan Hashtable on aina "riittävän" suuri. Hashtable-oliossa sekä avaimet että arvot ovat Object-tyyppisiä. Avaimena käytettävien olioiden luokan on toteutettava hashCode- ja equals-metodit (tästä ei tässä enempää; mm. String, Integer, Double, ... kelpaavat avaimiksi).
Joitakin Hashtable-luokan välineitä:
import java.util.*; public class HaEsim { public static void main(String[] args) { Hashtable taulu = new Hashtable(); String sana1, sana2; do { System.out.print("Sana alkukielellä? (tyhjä lopettaa) "); sana1 = Lue.rivi(); if (sana1.equals("")) break; if (taulu.containsKey(sana1)) { System.out.println("Sana \"" + sana1 + "\" löytyy jo!"); System.out.println("Vanha käännös " + "\"" + taulu.get(sana1) + "\" jää voimaan!"); continue; // uusi alkukielinen sana } System.out.print("Sana käännettynä? (tyhjä lopettaa) "); sana2 = Lue.rivi(); if (sana2.equals("")) break; // nyt molemmat sanat ovat ei-tyhjiä ja ensimmäinen on uusi taulu.put(sana1, sana2); } while (true); // loppuu jomman kumman sanan ollessa "" System.out.println(taulu); do { System.out.print("Minkä sanan käännöksen haluat tietää? " + "(tyhjä sana lopettaa) "); sana1 = Lue.rivi(); if (sana1.equals("")) break; if (!taulu.containsKey(sana1)) System.out.println("Sanan \"" + sana1 +"\" käännös on tuntematon!"); else System.out.println("Sanan \"" + sana1 + "\" käännös on \"" + "\"" + taulu.get(sana1) +"\""); } while (true); // loppuu tyhjään sanaan } }