Avdeling for informatikk og e-læring, Høgskolen i Sør-Trøndelag

 

Leksjon 2: Tabeller av referanser og klassen ArrayList

Else Lervik
Lærestoffet er utviklet for faget LO191D Videregående programmering

Opphavsrett: Else Lervik og Stiftelsen TISIP


Resymé: Hovedtemaet for denne leksjonen er samlinger av objekter av samme type, for eksempel en gruppe med studenter, en mengde biler eller en samling CD-plater. Slike samlinger kan vi lagre i tabeller, eller vi kan bruke en ferdigdefinert klasse, klassen java.util.ArrayList. Å bruke klassen har flere fordeler, som vi ganske snart skal se. Hensikten med dagens innleveringsoppgave er å utforske de to forskjellige måtene å lagre objektsamlinger på.

Referanse til læreboka: Kapittel 8.7, 12.2, 12.3, 13.1-13.3, 13.5

Innhold

Innledning   
Repetisjon: Tabell av strenger
Tabell av studentobjekter    
Klassen ArrayList    
Kan vi legge tall inn i en ArrayList? 


Innledning

I forrige leksjon var temaet tabeller av strenger. Ettersom en streng er et objekt og navnet på en streng dermed er en referanse, er det i prinsippet ikke noe forskjell på tabellbehandlingen i denne og i forrige leksjon. Nå viser det seg imidlertid at mange studenter syns det er mye vanskeligere med andre typer objekter enn strenger. Derfor er dette temaet tatt opp i en egen leksjon.

En noe trasig begrensning ved tabeller er at lengden ikke kan forandres etter at tabellen er laget. Dersom vi har behov for en større tabell, må vi lage en ny som er større og kopiere over dataene fra den gamle tabellen til den nye. Dette er selvfølgelig tungvint. Det er derfor laget en klasse, java.util.ArrayList, der blant annet dette er skjult for oss. Ved å bruke denne klassen i stedet for en vanlig tabell, sparer vi en del arbeid. I praksis bruker vi nesten alltid klassen ArrayList når tabellen vår varierer i lengde. 

Etter å ha gått gjennom tabeller av objekter, skal vi se hvordan vi bruker klassen ArrayList.

Repetisjon: Tabell av strenger

Vi har en tabell av strenger:

  String[] navneliste = new String[4];

Vi må videre gi verdi til hvert enkelt objekt:

  navneliste[0] = "Hanne";
  navneliste[1] = "Berit";
  .. osv ..

Vi sender meldinger til et av objektene slik:

    if (navneliste[0].equals(etNavn)){
      ...
    }
    String storeBokstNavn = navneliste[1].toUpperCase();

Tabell av student-objekter

Vi har klassen Student og klassen Navn

Vi lager en tabell med  tre referanser til objekter av klassen Student.

    Student[] gruppe = new Student[3];

Vi har ennå ikke laget objektene. Hvert enkelt objekt må lages og legges inn i tabellen:

    gruppe[0] = new Student("Kåre", "Ulfsen", 19801212);
    gruppe[1] = new Student("Anders", "Vik", 19770510);
    gruppe[2] = new Student("Tove", "Ås", 19831002);

Merk denne to-trinns prosessen: Først lager vi en tabell av referanser, deretter må hvert enkelt objekt lages.

Anta nå at vi har tabellen gruppe, slik den er laget foran. Finn ut hva som skrives ut når vi nå kjører følgende kodebit:

    Student[] kopier = new Student[3];
    for (int i = 0; i < gruppe.length; i++) {
      kopier[i] = gruppe[i];
    }
    gruppe[1] = new Student("Eva", "Ås", 19800506);
    gruppe[2].setEtternavn("Bjørndal");
    System.out.println("Gruppe: ");
    for (int i = 0; i < gruppe.length; i++) {
      System.out.println(gruppe[i].getFornavn() + " " + gruppe[i].getEtternavn());
    }

    System.out.println("Kopier: ");
    for (int i = 0; i < kopier.length; i++) {
      System.out.println(kopier[i].getFornavn() + " " + kopier[i].getEtternavn());
    }
 

Løsning.

Stemte det? Hvis ikke, har du husket på at kopieringen i linje 2 ikke fører til at vi får nye objekter, men bare et sett med nye referanser til de eksisterende objektene? Videre: Setningen 

    gruppe[1] = new Student("Eva", "Ås", 19800506);

fører til at referansen gruppe[1] nå peker til "Eva Ås", mens kopier[1] fremdeles peker til "Anders Vik". Neste setning

    gruppe[2].setEtternavn("Bjørndal");

endrer etternavnet til det objektet som gruppe[2] peker til. Men husk at referansen kopier[2] også peker til dette objektet.

ArrayList

Jeg tipper at klassen java.util.ArrayList vil bli en av de ferdigdefinerte klassene du kommer til å bruke aller mest i din Java-karriere. Du skal derfor bruke mye tid på denne klassen. Den er sentral i innleveringsoppgavene både denne gang og neste gang, og også i senere oppgaver. Les side 420-422 (kapittel 13.1) i boka. Gjør oppgavene i slutten av delkapitlet. Løsning finner du på bokas hjemmeside.

Les også kapittel 13.2 om utvidet for-løkke. Gjør oppgave 1 på side 424.

Sørg også for at du finner fram til ArrayList i online API-dokumentasjonen, det kan godt være du trenger flere metoder enn de som står i boka.

La oss fortsette med objekter av klassen Student:

ArrayList<Student> studenter = new ArrayList<Student>();
Student enStudent = new Student("Ole Petter", "Hansen", 19801212);
Student enStudentTil = new Student("Ingrid", "Olsen", 197512101);
Student endaEnStudentTil = new Student("Åse Marie", "Jensen", 19730506);
studenter.add(enStudent);
studenter.add(enStudentTil);
studenter.add(endaEnStudentTil);

Figuren nedenfor viser referansene og objektene:



Merk at det bare er referansene til objektene, og ikke objektene selv, vi legger inn i ArrayListen.

Vi antar nå at vi har deklarasjonene gitt foran. Hva blir skrevet ut når følgende programbit kjøres:

System.out.println("Utskrift 1: Antall studenter er " + studenter.size());
for (Student enStudent : studenter) {
  System.out.println(enStudent.getFornavn() + " " + enStudent.getEtternavn());
}

studenter.remove(1);
System.out.println("Utskrift 2: Antall studenter er " + studenter.size());
for (Student enStudent : studenter) {  // merk at vi bruker utvidet for-løkke
  System.out.println(enStudent.getFornavn() + " " + enStudent.getEtternavn());
}

studenter.add(enStudentTil);
studenter.add(endaEnStudentTil);
System.out.println("Utskrift 3: Antall studenter er " + studenter.size());
for (Student enStudent : studenter) {
  System.out.println(enStudent.getFornavn() + " " + enStudent.getEtternavn());
}

studenter.set(2, new Student("Anne", "Iversen", 19801212));
System.out.println("Utskrift 4: Antall studenter er " + studenter.size());
for (Student enStudent : studenter) {
  System.out.println(enStudent.getFornavn() + " " + enStudent.getEtternavn());
}

Løsning.

I tilknytning til ukens øving leser du kapittel 13.5.

Kan vi legge tall inn i en ArrayList?

Vi har sett hvordan klassen ArrayList er et godt alternativ til å bruke objekttabeller med variabel lengde. Men hva med talltabeller med variabel lengde? Behovet er der, helt klart. Både for talltabeller og tabeller av andre primitive datatyper ... Det er da vi tar i bruk wrapperklassene for de primitive datatypene. Jeg vet ikke om du fikk med deg dette i grunnkurset (se ev. side 251-252); veldig kort så handler det om klasser der hvert objekt har plass til eksakt én verdi av en primitiv datatype. Og (referanser til) disse objektene kan vi legge inn i ArrayLister.

Her er en liste over de primitive datatypene: boolean, byte, char, short, int, long, float og double
De tilhørende klassene har navnene Boolean, Byte, Character, Short, Integer, Long, Float og Double

Eksempel, der vi legger tallet 50 inn i et Integer-objekt:

Integer heltallsobjekt = new Integer(50);

Eventuelt kan vi bruke kortformen:

Integer heltallsobjekt = 50;

Her skjer det en automatisk omforming fra heltallet 50 til et Integer-objekt. Omvendt:

int etTall = heltallsobjekt.intValue();

eller, kortere (automatisk omforming):

int etTall = heltallsobjekt;

Les kapittel 13.3 (side 424-425) i boka.