Observera att detta är en arbetsversion av sidan!
Dölj style3dev.css för att bli av med annoteringarna!

Lektion 6: Arrayer

Innehåll: Arrayer, iterationer över arrayer, data som index, arrayer med objekt.
Begrepp som introduceras: Arrayer. "for-each"-satsen.
Arbetssätt: Arbeta gärna tillsammans med någon men skriv egen kod. Diskutera med varandra!
Använd debuggern för att hitta fel!
Uppskattad arbetstid: 4 timmar. Notera gärna hur lång tid du själv behöver och framför det vid nästa redovisningstillfälle! ?
Redovisning: Materialet redovisas under lektion 7. Uppgifterna och frågorna är viktiga!

Arrayer

En array är en datatyp som innehåller flera värden. Alternativa namn är fält och vektor liksom även indicerad variabel och tabell.

I Java hanteras arrayer som objekt dvs man skapar arrayobjekten med new och hanterar dem med referenser. De individuella värdena (''arrayens element'') numreras från noll och uppåt. Elementets nummer kallas index.

Det går att ha vilken datatyp som helst i en array (inklusive objektreferenser) men alla element i en array måste ha samma datatyp.

Prova nedanstående instruktioner i tur och ordning i interaktionsrutan.

(Klicka här om du inte har tillgång till interaktionsrutan!)

(Om man inte har tillgång till DrJava med interaktionsrutan så kan man lägga koden i en main-metod och använda java.util.Arrays.toString(a) för utskrifter. Utskrifterna av arrayer med System.out.println blir aldrig bra.).
Prova Kommentar
int[] a; Skapar en arrayreferens. Den blir null eller odefinierad beroende på var deklarationen står.
a Variabeln a har inte tilldelats något array-objekt.
a = new int[8]; Skapar ett array-objekt med 8 heltal och låter a referera det. Alla individuella värden är 0.

Bild

Resultatet kan illustreras så här:

Det hade gått lika bra att skapa array-objektet samtidigt som vi deklarerade variabeln:
 int[] a = new int[8];

a Nu håller a i array-objektet
a[0] = 2; a[4] = 3; a[1] = 5; a[7] = 9; a[2] = a[0]*a[4] + 1 a[6]++;

Använder variabelnamnet följt index inom [] för att referera enskilda element.


Bild

Nu ser det ut så här:

System.out.println(a); Blir inte så vackert ...
a[-1] Felaktigt indexvärde
a[8] Fel eftersom elementen är numrerade 0..7
a.length Ger storleken på arrayen (obs: inga parenteser!)
int[] b = new int[]{3, 2, 1}; Det går att ge värden till arrayens element när man skapar objektet.
int[] b = {3, 2, 1}; I en deklaration kan man utelämna new[] vilket man vanligen gör.
int[] c = a;

Bild

Det går att ge sätta flera referenser till samma objekt:

c[1] = 8; Spelar ingen roll om vi använder a eller c. De refererar samma objekt!
b = c;

Bild

Variabeln b får ett annat objekt:

Sammanfattning Exempel
En array består av ett antal (1 eller flera) element alla av samma typ.
Arrayer är objekt och skapas med operatorn new.

Uttrycket new type[size] skapar en array med size element av typ type. Om type är primitiv blir alla värden satta till 0 (eller false om boolean) annars null.

Uttrycket new type[] vlist skapar ett arrayobjekt med värden enligt den kommaseparerade listan vlist.

new double[5] new String[10] new Turtle[100] new int[]{1, 2, 3, 4, 5}
För att hålla reda på arrayer används referensvariabler.
Deklareras med type[] name.

Kan tilldelas arrayreferenser.

När man skapar objekten i variabeldeklarationen (men bara då) kan man utelämna type[] vilket man vanligen gör (jämför b och c i exemplen bredvid).

int[] a; int[] b = new int[]{1, 2, 3, 4; int[] c = {4, 5, 6}; a = b; b = new int[]{7, 8, 9}; String[] s = new String[10]; Turtle[] t = new Turtles[100];
Ett arrayobjekt har en fix storlek som inte kan ändras.
Storleken kan avläsas i attributet length

En arrayreferens kan tilldelas arrayobjekt av en annan storlek.

if (a.length > b.length)     b = a; }

Iterationer över arrayer

För att hantera alla (eller många) av elementen i en array används iterationssatser.

Här följer några exempel:

Denna kod summerar alla värden i arrayen som a refererar med hjälp av en for-sats:
int sum = 0; int index = 0; while (index < a.length) { sum = sum + a[index]; index++; }

(Du kan markera den och klistra in den i interaktionsrutan under förutsättning att du har en array-referensen a är initierad. Undersök vad variablerna sum och index är!)

När man skall hantera alla element i en array föredrar man ofta en for-sats framför en while-sats.

Denna kod summerar alla värden i arrayen som a refererar med hjälp av en for-sats.
int sum = 0; for (int index = 0; index < a.length; index++) { sum = sum + a[index]; }

Vi har alltså "flyttat in" dels deklarationen och initieringen av räknaren index (dvs int index = 0) och dels ökningen av räknaren (dvs index++) i parentesen efter for

Lite kompaktare och kanske tydligare men exakt samma funktion koden med while-satsen.

En skillnad dock: i fallet med while-satsen existerar variabeln index efter iterationens slut och har värdet a.length men efter for-satsen slut existerar den inte alls.

(Se minilektionerna om for-satsen respektive while-satsen).

Anmärkning: Ovan har vi använt index som namn på iterationsvariabeln. Det är ett bra och tydligt namn men ofta föredrar man ett kortare namn (typiskt i och j).

"for each"-satsen

Det finns en speciell variant av for-satsen som passar bra när man vill behandla alla elementen i en array.

Med denna kan exemplet ovan skrivas:
int sum = 0; for (int e : a) { sum = sum + e; }

Variabeln e kommer successivt anta alla enskilda elements värden dvs a[0], a[1], etc.


 
Ett till exempel:
String[] words = {"Hej", "du", "glade"}; for (String w : words) { System.out.println(w); }

Iterationsvariabeln (i detta exempel w) ska alltså ha samma typ som elementen i arrayen.

Observera: Denna variant av for-loopen passar bara bra när man ska besöka alla element i arrayen och dessutom inte är intresserad av elementens index.

Övningar

  1. Några operationer på en array i main-metoden
    1. Skapa en ny klass ( i DrJava-menyn).
    2. Kopiera in klassen ArrayTest. Kompilera.
    3. Kör programmet.
    4. Gör de övningar so är angivna i main-metoden.
  2. Klassen RandomArray

    Detta är en klass som har en array med heltal som enda instansvariabel. Arrayen fylls med slumptal när objektet skapas. Meningen med klassen är att du ska öva på att skriva metoder som gör olika saker med arrayen.

    1. Skapa en ny klass ( i DrJava-menyn.)
    2. Kopiera in klassen RandomArray. Kompilera.
    3. Skriv en main-metod som skapar tre RandomArray-objekt användande var och en av de tre olika konstruktorerna. Skriv ut de tre objekten med hjälp av toString-metoden.
    4. Skriv metoden getLast() som returnerar det sista värdet i arrayen. Lägg in kod i main som demonstrerar metoden.
    5. Skriv metoden maxValue() som beräknar och returnerar det största värdet i den lagrade arrayen. Använd "for each"! Lägg in testkod för den i main.
    6. Skriv metoden maxIndex() som beräknar och returnerar index för det största elementet i den lagrade arrayen. Kan man använda "for-each"? Lägg in testkod för den i main.
    7. Hur skulle du löst uppgift 5 om du först löst uppgift 6?
    8. Skriv en metod public boolean exists(int value) som letar efter value i arrayen och returnerar true om det finns, annars false. Lägg in testkod för den i main.
    9. Prova följande kod:
      RandomArray a = new RandomArray(); int b = a[3];
      Varför fungerar det inte? Hur måste man skriva?
    10. Klassen RandomArray innehåller bara en enda instansvariabel (en array). Vad är det då för mening med att göra en klass?
  3. Tärningsstatistik

    Skriv en klass TestDice med en main-metod. Metoden skall testa en tärning genom att slå den upprepade gånger och räkna hur många gånger varje möjligt utfall förekommer.

    Du skall givetvis använda klassen Dice från en tidigare lektion!

    Metoden skall börja med att fråga användaren om hur många sidor tärningen skall ha och hur många slag som skall göras. Läs minilektionen om Scanner-klassen för att se hur man läser tal från tangentbordet.

    Programmet skall skriva ut en tabell med utfall, antal gånger med det utfallet samt utfallets relativa frekvens.

    Så här kan en körning av main-metoden se ut:
    Ge antal sidor: 6 Ge antal slag: 1000 1 161 0.161 2 162 0.162 3 174 0.174 4 167 0.167 5 164 0.164 6 172 0.172

    Det finns en minilektion som beskriver hur man gör en frekvenstabell.

    Kom ihåg att använda debuggern för felsökning!

  4. Arrayer med objekt.

    Elementen i en array är inte begränsade till primitiva datatyper utan kan även vara objektreferenser t ex strängar (String) eller paddor (Turtle). Läs gärna minilektionen som handlar om arrayer av objekt.

    1. Skriv en klass StrollingTurtles2 med en main-metod som skapar en värld med n paddor som lagras i en array. Låt n vara en lokal variabel i main-metoden.
      Paddorna skall röra sig slumpmässigt i världen. Använd moveRandom() i klassen Turtle samt metoden Thread.sleep(x) från lektion 4.
    2. (Svårare). Modifiera programmet så att paddor som kommer närmare någon av världens kanter än 20 steg (metoden distanceToClosestWall() från lektion 3) skall förintas (tas bort).

      Metoden remove(t) i klassen World tar bort det objekt som t refererar ur världen men den försvinner ju inte från den array som håller i paddorna.
      (Tips: du kan sätta ett arrayelement till null men då måste du undvika att använda det.)
      Om du inte vill att spåren av paddan ritas ut använd metoden t.disablePath().

    3. (Överkurs) Modifiera programmet så att om två paddor krockar (avstånd mindre än 5) uppstår ett barn dvs en till padda med sannolikheten 0.25. För att det skall gå att skapa nya paddor så måste det finnas utrymme i arrayen. Gör alltså arrayen ganska stor (100 platser?) utan att fylla den. Starta t ex med 20 paddor.
    4. (Överkurs) I stället för att försvinna när de kommer till en vägg skall de studsa (infallsvinkel lika med utfallsvinkel på sedvanligt sätt). Låt också paddorna dö med en viss sannolikhet. Avbryt när alla paddor försvunnit ur världen.

Gå till nästa lektion eller gå tillbaka

Valid CSS!