Arrays

Kommode Folgendes Problem:

Wir wollen 10 Preise einlesen und den niedrigsten markieren:

19.95
23.95
24.95
18.95 <- niedrigster Preis
29.95
19.95
20.00
22.99
24.95
19.95

Alle Daten müssen eingelesen werden, bevor wir ausgeben können, daher müssen wir sie zwischenspeichern. Dafür zehn Variablen zu verwenden wäre sehr unflexibel. Was nun?

Durch

double[] data = new double[10];

deklarieren wir ein Array von Double-Werten der Größe 10.

Genauer:

  1. Ein Array ist ein Verweis auf eine Abfolge fester Länge von Variablen des gleichen Typs, genannt Fächer (engl. slots).
  2. Der Typ typ[] ist der Typ der Arrays mit Einträgen vom Typ typ.
  3. Der Ausdruck new typ[n] liefert ein frisches Array vom Typ typ der Länge n zurück. Hier ist n ein Ausdruck vom Typ double.

Im Beispiel ist also data eine Arrayvariable, die ein frisches Array vom Typ double der Länge 10 enthält.

Im Rechner ist der Arrayinhalt als Block aufeinanderfolgender Speicherzellen repräsentiert. Das Array selbst ist ein Objekt, bestehend aus der Länge und der Speicheradresse des Blocks.

Fragen

  1. Bitte in einem neuen Projekt eine Klasse Felder erstellen, welches das Array aus obigem Beispiel enthält. Anschließend mit dem Objekt-Inspektor inspizieren und obige Erklärung nachvollziehen…

Array-Zugriff

Durch

data[4] = 29.95;

setzen wir das Fach mit der Nummer 4 auf den Wert 29.95. Mit

System.out.println("Der Preis ist EUR" + data[4]);

können wir diesen Wert ausgeben.

data[4] verhält sich ganz genauso wie eine "normale" Variable vom Typ double.

Ist a ein Array und i ein Ausdruck des Typs int, so bezeichnet a[i] das Fach mit Index i des Arrays a.

Achtung: Diese Indizes beginnen bei Null (wie bei den Strings auch!). Es muss also i echt kleiner (eins weniger) als die Länge von a sein.

Im Beispiel sind die Fächer also

data[0], data[1], data[2], data[3], ... , data[9]

Länge

Ist a ein Array, so ist

a.length

die Länge des Arrays als Integer. (Achtung: nicht a.length()!!!)

Das ist nützlich, wenn man die Länge später (durch Editieren und Neukompilieren) vergrößern muss. a.length stellt sich dann automatisch mit um. Ein "festverdrahteter" Wert wie 10 müsste auch explizit umgeändert werden.

Die Länge wird abgerufen wie eine als public deklarierte (Instanz)variable. Man kann sie aber im Programm nicht verändern, d.h.

a.length = 20;

ist nicht erlaubt.

Wichtiges im Überblick

  1. Ein Array ist ein Verweis auf eine Folge von Variablen, der sogenannten Fächer.
  2. Arraytypen werden durch Anfügen von eckigen Klammern gebildet.
    Ein Arraytyp ist weder Objekt- noch Grunddatentyp.
  3. Frische Arrays werden mit new erzeugt; die Länge des Arrays wird in eckigen Klammern angegeben.
  4. Die Fächer eines Arrays werden durch Anfügen des in eckige Klammern gesetzten Index bezeichnet.
  5. Ein auf diese Weise bezeichnetes Fach ist eine Variable. Man kann ihren Wert verwenden und ihr mit = einen neuen Wert zuweisen.
  6. Arrayindizes beginnen immer bei 0 (wie bei String).
  7. Die Länge eines Arrays erhält man mit .length

Idiom für die Arrayverarbeitung

Merke: Das "Durcharbeiten" eines Arrays erfolgt meist so:

for(int i = 0; i < a.length; i++) {
    ...
    // Bearbeiten des Faches mit Index i
    ...
}

Vorsicht mit Arrayvariablen

double[] data;
System.out.println(data[5]);

ist falsch. data[5] wurde ja nicht initialisiert.

double[] data;
data[5] = 7;
System.out.println(data[5]);

ist aber auch falsch!

"new" nicht vergessen

Der Grund ist, dass die Variable data selber noch gar nicht initialisiert wurde.

Man muss so einer Variable erst ein Array (= Verweis auf Folge von Variablen) zuweisen. Normalerweise macht man das mit new:

double[] data;
data = new double[10];

Man kann aber auch direkt einen Arrayausdruck zuweisen, z.B.

double[] data = {0,1,2,3,4,5,6,7,8,9};

Arrays als Methodenparameter

Eine Array kann als Parameter übergeben werden:

public double mittelwert(double[] zahlen) {
    if (zahlen.length == 0) {
        return 0.0;
    }
    double summe = 0;
    for(int i = 0; i < zahlen.length; i++) {
        summe = summe + zahlen[i];
    }
    return summe/zahlen.length;
}

Man kann nun etwa mittelwert(data) aufrufen. Wert ist der Mittelwert von data.

Arrays als Rückgabewerte

Ein Arraytyp kann auch als Rückgabewert in Erscheinung treten. Hier ist eine Methode, die die Eckpunkte eines regelmäßigen n-Ecks zurückgibt:

/* Gibt die einzelnen Eckpunkte eines regelmäßigen Polygons mit
 * n Ecken,
 * dem Mittelpunkt zentrum und
 * Radius radius
 * aus
 */
public getPunkt[] nEck(int n, Punkt zentrum, double radius) {
    Punkt[] result = new Punkt[n];
    // Berechnung mit sin und cos
    // ... bitte ergänzen...
    // anschließend Rückgabe des Punkte-Arrays
    return result;
}

Finden eines Wertes

Man möchte wissen, ob einer der eingelesenen Preise ≤ 1000 ist:

boolean gefunden = false;
for(int i = 0; i < data.length; i++)
    gefunden = gefunden || (data[i] <= 1000);
    // wer das erklären kann, ist gut!

jetzt ist gefunden true genau dann, wenn data einen Eintrag ≤ 1000 hat. Man möchte nun auch noch wissen, wie viele Preise ≤ 1000 sind:

int count = 0;
for(int i = 0; i < data.length; i++)
    if (data[i] <= 1000)
        count++;

Jetzt ist count gleich der Anzahl derjenigen Preise, die ≤ 1000 sind.

Löschen eines Wertes

Man möchte den Eintrag an der Stelle pos aus einem teilweise gefüllten Array löschen.

Falls die Ordnung keine Rolle spielt:

// Definition für die intern benutzte Länge:
dataSize = data.length;
 
// Das zu löschende Element an der Stelle pos
// mit dem letzten Element überschreiben
data[pos] = data[dataSize-1]; 
 
// die intern verwendete Längenangabe reduzieren
dataSize  = dataSize - 1;
 
// Achtung: data.length hat sich nicht verändert!

Falls die Ordnung beibehalten werden muss:

// Elemente bis zur Position aufschieben
for(int i = pos; i < dataSize - 1; i++)
    data[i] = data[i+1];
 
// die intern verwendete Längenangabe reduzieren
dataSize = dataSize - 1;

Einfügen eines Elements

…an der Stelle pos unter Beibehaltung der Ordnung:

for(int i = dataSize; i > pos; i--)
    data[i] = data[i-1];
 
data[pos] = neuerWert;
dataSize = dataSize + 1;

Man muss sich immer wieder sehr genau klar machen, was hier passiert.

In der Anwendung muss man natürlich sicherstellen, dass pos nicht außerhalb der Grenzen liegt.

Arrays als Instanzvariablen

Arrays können auch als Instanzvariablen eines Objektes in Erscheinung treten. Es empfiehlt sich, dann im Konstruktor auch gleich ein frisches Array zu erzeugen.

Beispiel:

public class Polygon {
    private int n;         // Zahl der Ecken
    private Point[] ecken; // Liste der Ecken
 
    /* Methoden und Konstruktoren */
}

Zweidimensionale Arrays

Die Einträge eines Arrays können wieder Arrays sein. Das gibt ein zweidimensionales Array.

int[][] einmaleins = new int[10][10];
 
for(int i = 0; i < 10; i++) {
    for(int j = 0; j < 10; j++) {
        einmaleins[i][j] = (i+1) * (j+1);
    }
}

Fragen

  1. Erkläre, was an diesem Codefragment falsch ist und gib an, wie man es besser macht:
    int[] v = new int[10];
    for(int i = 1; i <= 10; i++)
        v[i] = v.length - i;

    Was steht nach erfolgreicher Ausführung der Schleife im Array? (Bitte selbst durchspielen und nicht laufen lassen…)

  2. Gib Beispiele für eine sinnvolle Methode, die…
    • einen formalen Parameter vom Typ int[] hat, der modifiziert wird.
    • einen formalen Parameter vom Typ int[] hat, der nicht modifiziert wird.
    • die ein Array vom Typ int[] zurückgibt.
  3. Schreibe eine Schleife, die ein Array wie folgt besetzt: 1 4 9 16 25 36 49 64 81 100
  4. Konstruiere ein 2D-Array von Booleans, das schachbrettartig vorbesetzt ist.
  5. Schreibe eine Methode, die überprüft, ob zwei Arrays dieselben Elemente in derselben Reihenfolge enthalten.
  6. Lade folgende Datei herunter und benenne Sie in "Felder.java" um: felder.txt
    1. Öffne BlueJ.
    2. Schließe evtl. bereits geöffnete Projekte.
    3. Erstelle ein neues Projekt "Felder".
    4. Erstelle darin eine Klasse "Felder".
    5. Kopiere den Inhalt der oben angegebenen Klasse an Stelle der automatisch generierten Codezeilen in deiner soeben erstellten Klasse und speichere ab.
    6. Fang an die Arbeitsaufträge abzuarbeiten (Methoden implementieren und kommentieren). Und ab geht's! :-)
start/info/11if/09_arrays.txt · Zuletzt geändert: 11.06.2015 12:22 von epunkta
www.chimeric.de Creative Commons License Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0