H12 Tabellen

Leerdoelen

Na het bestuderen van dit hoofdstuk wordt van je verwacht dat je:

  • weet hoe je een tabel (array) maakt
  • weet hoe je waardes in een tabel declareert en op verschillende manieren instantieert
  • hoe je met een for- en while-lus door een tabel kunt gaan
  • weet hoe je de lengte van een tabel kunt opvragen
  • weet hoe je een ondiepe kopie (shallow copy) en een diepe kopie (deep copy) van een tabel kunt maken en wat het verschil is
  • weet hoe je waardes in een tabel kunt zoeken
  • weet hoe je een tabel kunt sorteren

Praktijk

Inleiding

Een tabel is een rij gelijksoortige gegevens in het intern geheugen van de computer. Een tabel betekent hier iets geheel anders dan een tabel in een database. Met gelijksoortig wordt bedoeld dat een tabel uit of een aantal objecten of uit waarden van hetzelfde primitieve type bestaat.

Een tabel bestaat altijd uit een van tevoren vastgesteld aantal elementen. Het aantal elementen dat maximaal in de tabel kan worden opgenomen, heet de lengte of grootte van een tabel. Een tabel begint altijd bij element 0 en eindigt bij het aantal elementen min één. Elk element wordt in de tabel aangeduid met een geheel getal. Deze wordt de index genoemd.

Een tabel wordt ook wel een reeks of rij genoemd, in het Engels array.

Het maken van een tabel

Er zijn drie stappen nodig om een tabel te maken:

De tabel bestaat nu uit vijf elementen van het type double. Het eerste element wordt niet met 1 aangeduid maar met 0. Het laatste niet met 5 maar met 4 (= aantal - 1).

Een tabel kan heel makkelijk met het For-statement benaderd worden. Het volgende codefragment laat zien hoe je de tabel met een for-lus zou kunnen vullen in plaats van alle waardes afzonderlijk in te typen zoals hiervoor werd gedaan:

					
for (int teller = 0; teller < 5; teller ++)
    salaris[teller] = 100 * (teller + 1);

De teller teller begint bij 0 en de lus eindigt als de waarde in teller is opgelopen tot 5. Nog mooier is het Java de hoogste grens te laten bepalen:

					
for (int teller = 0; teller < salaris.length; teller ++)
    salaris[teller] = 100 * (teller + 1);

Nu hoeven we niet meer te weten hoe groot de tabel is.

Met de for-lus kan de tabel gemakkelijk op het scherm gezet worden:

					
for (int teller = 0; teller < salaris.length; teller ++)
    g.drawString("" + salaris[teller], 50, 20 * teller + 20);

het gehele programma ziet er als volgt uit:

//Voorbeeld 12.1

import java.awt.*;
import java.applet.*;

public class Tabel extends Applet {
    double salaris[];
	
    public void init() {
        salaris = new double [5];
		
        for (int teller = 0; teller < salaris.length; teller ++) {
            salaris[teller] = 100 * teller + 100;
        }
    }

    public void paint(Graphics g) {
        for (int teller = 0; teller < salaris.length; teller ++) {
            g.drawString("" + salaris[teller], 50, 20 * teller + 20);
        }
    }
}

Het maken van een kopie

Soms moeten de waarden worden gekopieerd van de éne naar een andere tabel. Je zou daarbij de volgende regel kunnen gebruiken:
kopie = salaris

Als vervolgens de elementen van kopie op het scherm wordt gezet, dan lijkt het alsof er een kopie van is gemaakt. Dat is niet waar: Er is een referentie gemaakt.

Dit wordt een ondiepe kopie (shallow copy) genoemd. Wijzigingen die op kopie plaatsvinden, worden dus tevens voor salaris doorgevoerd.

Met een for-lus kunnen we een zogenaamde diepe kopie (deep copy) maken:

for(int teller = 0; teller < salaris.length; teller ++) {
    kopie[teller] = salaris[teller];
}

Als we nu een wijziging aanbrengen in de table kopie dan blijft de table salaris ongewijzigd:

De volgende programma's laten dit principe zien:

//Voorbeeld 12.2

import java.awt.*;
import java.applet.*;

public class Tabel extends Applet  {
    double[] salaris;
    double[] kopie;
	
    public void init() {
        salaris = new double[5];
        kopie = new double[5];

        for (int teller = 0; teller < salaris.length; teller ++) {
            salaris[teller] = 100 * teller + 100;
        }
        kopie = salaris;
        kopie[3] = 1000;  //salaris[3] wordt nu ook gewijzigd!
    }

    public void paint(Graphics g) {
        for (int teller = 0; teller < salaris.length; teller ++) {
            g.drawString("" + kopie[teller], 50, 20 * teller + 20);
            g.drawString("" + salaris[teller], 100, 20 * teller + 20);
        }
    }
}
//Voorbeeld 12.3

import java.awt.*;
import java.applet.*;

public class Tabel extends Applet  {
    double[] salaris;
    double[] kopie;
	
    public void init() {
        salaris = new double[5];
        kopie = new double[5];

        for (int teller = 0; teller < salaris.length; teller ++) {
            salaris[teller] = 100 * teller + 100;
        }
         for (int teller = 0; teller < salaris.length; teller ++) {
             kopie[teller] = salaris[teller]
         }
        kopie[3] = 1000;  //salaris[3] wordt nu niet gewijzigd!
    }

    public void paint(Graphics g) {
        for (int teller = 0; teller < salaris.length; teller ++) {
            g.drawString("" + kopie[teller], 50, 20 * teller + 20);
            g.drawString("" + salaris[teller], 100, 20 * teller + 20);
        }
    }
}

Test beide applets. In voorbeeld 12.2 is de waarde in het vierde element in beide tabellen 1000 geworden, in voorbeeld 12.3 is alleen in kopie de waarde van het vierde element 1000 geworden.

Een tabel initialiseren

Een tabel initialiseren betekent dat de beginwaarden in een tabel gezet worden. Dat gaat het snelst op de volgende manier:

double[] salaris = { 100, 200, 300, 400, 500 };

Dat is alleen maar mogelijk als van tevoren bekend is, wat de beginwaarden van een tabel moeten zijn. Als de beginwaarden niet bekend zijn, kun je de tabel standaard-beginwaarden meegeven, bijvoorbeeld een nul.

Grootste waarde in een tabel

Soms moet de grootste of de kleinste waarde in een tabel gezocht worden. Dat kun je doen door de tabel met een for-lus te doorlopen. In onderstaand voorbeeld is de eerste waarde de grootste die tot dan toe is waargenomen. Die waarde zetten we in de variabele waarin we de grootste bewaren. Als in de lus een grotere waarde wordt gevonden, dan zetten we die in de variabele:

//Voorbeeld 12.4

import java.awt.*;
import java.applet.*;

public class Tabel extends Applet {
    double[] salaris = { 100.0, 200.0, 500.0, 400.0, 300.0 }; 
    double maximum;
    
    public void init() {
        maximum = salaris[0];
        for (int teller = 0; teller < salaris.length; teller ++) {
            if(salaris[teller] > maximum) {
                maximum = salaris[teller];
            }
        }
    }

    public void paint(Graphics g)  {
        g.drawString("Het maximum is: " + maximum, 50, 20);
    }
}
    

Wanneer je de kleinste wilt zoeken hoef je alleen het groter-dan (>) teken te vervangen met kleiner-dan (<)

Zoeken in een tabel

Het zoeken in een tabel gaat op een vergelijkbare wijze. Je begint bij het eerste element en je zoekt totdat de waarde die je zocht is gevonden of tot het einde van de tabel. Om te kunnen weten, of een waarde is gevonden, maken we een hulpvariabele van het type boolean. Deze heeft maar twee mogelijke waarden: waar of niet waar (true / false).

//Voorbeeld 12.5

import java.awt.*;
import java.applet.*;

public class Tabel extends Applet {
    boolean gevonden;
    double[] salaris = { 100.0, 200.0, 500.0, 400.0, 300.0 }; 
    double gezocht;
	
    public void init() {
        gezocht = 400;
        gevonden = false;
        int teller = 0;
        while(teller < salaris.length) {
            if(salaris[teller] == gezocht) {
                gevonden = true;
            }
            teller ++;
        }
    }

    public void paint(Graphics g) {
        if(gevonden == true) {
            g.drawString("De waarde is gevonden.", 20, 50);
        }
        else {
            g.drawString("De waarde is niet gevonden.", 20, 50);
        }
    }
}

Voorbeeld 12.5 heeft één nadeel. Als de gezochte waarde gevonden is, gaat de lus door met zoeken terwijl dat niet nodig is. Bij vijf elementen is dat niet erg, er is nauwelijks tijdverlies, maar bij een tabel van 100.000 elementen kan dat - zeker bij een ingewikkelde zoekopdracht - tijdrovend zijn. Er moet aan dit programma nog iets toegevoegd worden waardoor de lus stopt als de gezochte waarde is gevonden.

Sorteren

Sorteren is tegenwoordig niet meer moeilijk in Java. De klasse Arrays heeft een methode sort, waarmee gemakkelijk een tabel gesorteerd kan worden. Wel moet de package "util" geïmporteerd worden:

//Voorbeeld 12.6

import java.awt.*;
import java.applet.*;
import java.util.*;

public class Stringarrays extends Applet {
    String[] namen = { "Valerie", "Jeroen", "Sander", "Frank"}; 
	
    public void init() {
        Arrays.sort(namen);
    }

    public void paint(Graphics g) {
        for (int teller = 0; teller < namen.length; teller ++) {
            g.drawString("" + namen[teller], 50, 20 * teller + 20);
        }
    }
}

Tot slot

Behalve in het laatste voorbeeld zijn tot nu alleen doubles gebruikt voor tabellen, maar ook van bijvoorbeeld tekstvakken en van strings zijn op dezelfde manier tabellen te maken. In voorbeeld 12.6 zag je hoe een array van strings gemaakt kan worden.

Opdracht 12.1

Maak een applet in Java waarin een tabel van 10 getallen. Bereken het gemiddelde en zet de tien elementen en het gemiddelde op het scherm.

Opdracht 12.2

Maak een applet met een array van 25 knoppen. De knoppen hoeven niets te doen, maar moeten wel zichtbaar zijn.

Opdracht 12.3

Maak een applet waarin vijf tekstvakken (uiteraard in een tabel) worden getoond. In de tekstvakken moet de gebruiker getallen in kunnen voeren. Als de gebruiker op de Ok-knop klikt worden de getallen in de invoervolgorde gesorteerd getoond.

Opdracht 12.4

Zorg ervoor dat de lus waarin gezocht wordt naar een bepaalde waarde in voorbeeld 12.5 stopt als de waarde gevonden is.

Opdracht 12.5

Maak een applet met een tabel met getallen, waarin de gebruiker een getal kan intikken in een tekstvak. Als de gebruiker op de OK-knop klikt dan wordt de waarde opgezocht in de tabel en staat op het scherm niet alleen dat de waarde is gevonden maar ook de index. Als de waarde niet is gevonden dan wordt daarvan melding gedaan.

Opdracht 12.6

Maak een tabel, waarin elementen dezelfde waarde hebben. In de applet kan de gebruiker een waarde intikken. Vervolgens laat het programma de waarde zien en hoeveel keer de waarde voorkomt.

Praktijkopdracht

Schrijf een applet in Java, waarin de gebruiker 10 namen en 10 telefoonnummers kan invoeren. Telkens als de gebruiker op de Ok-knop klikt, wordt er naar de volgende elementen gegaan van de tabellen. Als de gebruiker na het tiende element op de Ok-knop klikt, worden alle elementen in het venster getoond.