Programmieren

Arrays

Um größere Datenmengen zu speichern, benutzen Sie am einfachsten und am effizientesten die Daten­struktur eines Arrays. Die Werte müssen alle vom gleichen Typ sein, also beispiels­weise alles int-Zahlen oder alles double-Zahlen oder alles Objekte (genauer: Verweise auf Objekte).

Eindimensionale Arrays

In einem ein­dimensionalen Array speichern Sie eine endliche Folge a0, ..., an-1 von Werten. Die Glieder ai der endlichen Folge werden in den Array-Einträgen a[i] gespeichert (i = 0, ..., n-1). Die Länge n der endlichen Folge, die Sie speichern möchten, muss bekannt sein, denn Sie müssen diese Länge angeben, wenn Sie das Array erzeugen.

Um ein Array anzulegen, sind drei Schritte erforderlich:

  1. Array deklarieren
  2. Array erzeugen (mit new)
  3. Array mit Werten belegen

Um beispiels­weise ein Array a mit den ersten sechs Primzahlen anzulegen, setzen Sie diese drei Schritte folgender­maßen um:

int[] a;         // Array a deklarieren
a=new int[6];    // Array a der Länge 6 erzeugen
a[0]=2; a[1]=3; a[2]=5; a[3]=7; a[4]=11; a[5]=13;    // Array a mit Werten belegen

 

  1. In der ersten Zeile deklarieren Sie ein Array mit dem Namen a, dessen Einträge vom Typ int sein sollen;
  2. in der zweiten Zeile erzeugen Sie das Array, und zwar mit der Länge n = 6. Hierdurch werden 6 Speicher­plätze für int-Zahlen bereit­gestellt, nämlich a[0], a[1], a[2], a[3], a[4], a[5];
  3. in der dritten Zeile belegen Sie diese Speicher­plätze mit Werten.

Technisch gesehen enthält die Variable a nicht das Array selbst, sondern einen Verweis auf die eigentlichen Speicher­plätze des Arrays.

Beachten Sie, dass in der Programmier­sprache Java die Array-Einträge immer von 0 beginnend nummeriert werden. Und die Nummerierung endet immer bei n-1, wenn n die Länge des Arrays ist.

Die Nummern, mit denen die Array-Einträge nummeriert sind, also im obigen Beispiel die Zahlen 0, ..., 5, werden auch als die Array-Indizes bezeichnet. Unter­scheiden Sie also immer zwischen den Array-Indizes und den eigentlichen Array-Einträgen. Das folgende Bild zeigt Ihnen das Array a mit den Array-Indizes 0, ..., 5 und den Array-Einträgen a[0] = 2, a[1] = 3, a[2] = 5, a[3] = 7, a[4] =11, a[5] = 13.

 0  1  2  3  4  5 
23571113
Array initialisieren

Das was Sie eben programmiert haben, geht auch kürzer:

int[] a = {2, 3, 5, 7, 11, 13};

Wenn Sie also ein einigermaßen kleines Array mit Werten initialisieren wollen, bietet sich diese Schreibweise an. Wenn Sie dagegen ein Array der Länge 1000 mit den Zahlen von 1 bis 1000 belegen wollen, benutzen Sie lieber eine For-Schleife.

Anders als in der Programmier­sprache C werden Arrays in Java nach der Erzeugung automatisch initialisiert, und zwar dem Wert 0 bei int-Arrays, mit 0.0 bei double-Arrays, mit false bei boolean-Arrays und mit null bei Objekt-Arrays.

Array mit For-Schleife durchlaufen

Um ein Array zu durchlaufen, beispiels­weise um die Einträge auf dem Bildschirm auszugeben, verwenden Sie am besten eine For-Schleife. Für das oben angegebene Array a lautet die For-Schleife wie folgt:

for (int i=0; i<6; i++)
    System.out.println(a[i]);

Die Länge des Arrays a lässt sich auch mit a.length ermitteln. Statt der 6 in obigem Programm schreiben Sie dann also a.length.

Um ein Array der Länge 1000 zu erzeugen und mit den Zahlen von 1 bis 1000 zu belegen, schreiben Sie

int[] a = new int[1000];    // Array deklarieren und erzeugen
for (int i=0; i<1000; i++)
    a[i]=i+1;
Array mit For-Each-Schleife durchlaufen

Wenn Sie nur lesend auf alle Array-Einträge zugreifen wollen, können Sie auch eine For-Each-Schleife verwenden:

for (int x : a)    // for each x in a
    System.out.println(x);

Sie können jedoch auf diese Weise nicht auf die Array-Indizes zugreifen und Sie können auch die Array-Einträge nicht verändern.

 

Arrays sind Objekte

Arrays sind in Java kein einfacher Datentyp wie etwa int oder double oder boolean, sondern ein Objekt-Datentyp. Eine Array-Variable enthält nicht das Array selbst, sondern einen Verweis auf das Array.

Um eine Kopie des ein­dimensionalen Arrays a der ersten sechs Primzahlen anzufertigen, genügt es leider nicht, einfach zu schreiben:

int[] b;
b=a;     // erzeugt keine Kopie des Arrays!

Hierdurch wird keine Kopie des Arrays a erzeugt, sondern es wird nur ein weiterer Verweis mit dem Namen b auf das Array a angelegt. Die Konsequenz ist, dass jede Änderung, die Sie im Array b durchführen, gleichzeitig auch im Array a stattfindet, und umgekehrt (denn a und b verweisen ja auf ein und dasselbe Array).

Weiter unten werden Sie sehen, wie Sie eine tatsächliche Kopie eines Arrays anfertigen.

Zweidimensionale Arrays

Ein ein­dimensionales Array ist wie eben gesehen so etwas Ähnliches wie eine Liste. Ein zwei­dimensionales Array ist so etwas Ähnliches wie eine Tabelle mit mehreren Zeilen und Spalten.

 0  1  2 
 0 123
1456

Sie deklarieren ein zwei­dimensionales Array wie folgt, hier beispiels­weise ein int-Array mit 2 Zeilen und drei Spalten:

int[][] a;
a=new int[2][3];

Technisch gesehen ist ein zwei­dimensionales Array ein ein­dimensionales Array, dessen Einträge Verweise auf ein­dimensionale Arrays sind, nämlich die Zeilen des zwei­dimensionalen Arrays. Theoretisch ist es sogar möglich, das Array so anzulegen, dass diese Zeilen unterschiedliche Länge haben; hierauf wird jedoch hier nicht eingegangen.

Auf einen Eintrag des Arrays a in Zeile i und Spalte j greifen Sie mit a[i][j] zu. So belegen Sie beispiels­weise das Array a mithilfe von zwei ineinander geschachtelten For-Schleifen mit Werten:

int k=1;
for (int i=0; i<2; i++)
    for (int j=0; j<3; j++)
        a[i][j]=k++;

Ein Trick: Der Ausdruck k++ ergibt den Wert der Variablen k und erhöht anschließend k um 1. So durchläuft k nacheinander die Werte 1, ..., 6. Sie können aber auch ausführlicher schreiben: {a[i][j]=k; k=k+1;}.

Wie Sie ein zwei­dimensionales Array mithilfe von zwei ineinander geschachtelten For-Schleifen durchlaufen, haben Sie soeben gesehen. Wenn Sie nur lesend auf die Einträge zugreifen möchten, können Sie auch zwei geschachtelte For-Each-Schleifen benutzen:

for (int[] r : a)
    for (int x : r)
        System.out.println(x);

Hier werden zunächst die Zeilen durchlaufen; jede Zeile wird als int-Array r angesprochen. Und dann wird jedes Array r sozusagen spaltenweise durchlaufen.

Array als Parameter einer Funktion

Wenn Sie öfter mit Arrays programmieren, legen Sie sich am besten einen Satz von sinnvollen Array-Funktionen zu. Sie können ein Array als Parameter an eine Funktion übergeben, und Sie können auch ein Array als Rückgabetyp einer Funktion festlegen.

Schreiben Sie zum Beispiel eine Funktion out, um ein ein­dimensionales int-Array auf dem Bildschirm auszugeben:

// eindimensionales Array ausgeben
public static void out(int[] a)
{
    for (int x : a)
        System.out.print(x+" ");
    System.out.println();
}

Die Funktion gibt die Einträge des Arrays neben­einander auf dem Bildschirm aus. Danach gibt sie noch einen Zeilen­vorschub aus.

Schreiben Sie als nächstes eine zweite Funktion out, um ein zwei­dimensionales int-Array auf dem Bildschirm auszugeben:

// zweidimensionales Array ausgeben
public static void out(int[][] a)
{
    for (int[] x : a)
        out(x);
    System.out.println();
}

Die beiden Funktionen dürfen den gleichen Namen out tragen, denn anhand des unterschiedlichen Parametertyps kann Java entscheiden, welche Funktion gemeint ist. Die zweite Funktion out ruft die erste Funktion out auf, um die Zeilen des zwei­dimensionalen Arrays auszugeben.

In ähnlicher Weise gehen Sie vor, um Arrays zu kopieren. Die folgende Funktion copy erzeugt eine Kopie eines ein­dimensionalen int-Arrays.

// eindimensionales Array kopieren
public static int[] copy(int[] a)
{
    int n=a.length;
    int[] b=new int[n];
    for (int i=0; i<n; i++)
        b[i]=a[i];
    return b; 
}

Hier ist der Rückgabetyp der Funktion ein int-Array. Einfacher ist es sogar noch, wenn Sie die eingebaute Array-Methode clone benutzen:

public static int[] copy(int[] a)
{
    return a.clone();
}

Wenn jedoch a ein zwei­dimensionales Array ist, fertigt die Methode clone leider nicht wie gedacht eine echte Kopie des zwei­dimensionalen Arrays an. Sie fertigt lediglich eine Kopie des ein­dimensionalen Arrays an, dessen Einträge Verweise auf die Zeilen des zwei­dimensionalen Arrays sind. Von den Einträgen der Zeilen werden keine Kopien angefertigt.

Wenn Sie also anschließend einen Eintrag im Array a ändern, schlägt dies unweigerlich auf die Kopie durch – und auch umgekehrt: Wenn Sie in der Kopie einen Eintrag ändern, schlägt dies auf das Original durch. Dies liegt daran, dass die Zeilen gar nicht kopiert worden sind, sondern nur die Verweise auf die Zeilen.

Setzen Sie also keine großen Erwartungen in die Methode clone. Sie klont nur die einfachen Datentypen wie int, double oder boolean zuverlässig. Bei Objekt-Datentypen, so auch bei Arrays, klont sie zuverlässig die Verweise – aber dies ist meistens nicht das, was Sie gewünscht haben.

Zweidimensionales Array kopieren

Die Funktion copy für ein zwei­dimensionales int-Array lautet wie folgt:

// zweidimensionales Array kopieren
public static int[][] copy(int[][] a)
{
    int n=a.length;
    int[][] b=new int[n][];
    for (int i=0; i<n; i++)
        b[i]=copy(a[i]);
    return b;
}

Hier wird bei der Erzeugung des Arrays b die zweite Dimension zunächst offen gelassen. Technisch gesehen wird also zunächst nur ein ein­dimensionales Array der Länge n erzeugt, dessen Einträge Verweise auf int-Arrays sind, die aber noch nicht mit Werten versehen sind. Sie erhalten ihre Werte erst später als Rückgabe­werte der Aufrufe von copy für ein­dimensionale Arrays.

Mehrdimensionale Arrays

Es gibt auch drei­dimensionale Arrays, und sogar 4-dimensionale Arrays. Sie können sich kein 4-dimensionales Array vorstellen? Doch!

Aber wozu braucht man 4-dimensionale Arrays? Nun, in vielen Fällen erhalten Sie mehrdimensionale Arrays dadurch, dass Sie viele Arrays mit weniger Dimensionen vorliegen haben und diese in systematischer Weise abspeichern möchten.

Es spricht also überhaupt nichts gegen beispiels­weise folgende Deklaration und Erzeugung eines 4-dimensionalen Arrays von Integer-Zahlen:

int[][][][] a = new int[N4][N3][N2][N1];

wobei N1, ..., N4 Konstanten sind, mit denen Sie die Ausmaße des Arrays in den einzelnen Dimensionen angeben.

Selbstverständlich können Sie sich ein 4-dimensionales Array auch als 2-dimensionales Array vorstellen, dessen Einträge 2-dimensionale Arrays sind, also quasi als zwei­dimensionale Tabelle, wobei die Tabellen­einträge wiederum zwei­dimensionale Tabellen sind.

Das folgende Programm­stück gibt Ihnen nacheinander alle diese 2-dimensionalen Arrays b aus, aufgefasst als Einträge des 2-dimensionalen Arrays a – im Beispiel also die Ergebnisse aller Spieltage:

for (int i=0; i<N4; i++)
    for (int j=0; j<N3; j++)
    {
        int[][] b=a[i][j];
        out(b);
    }

 

Ob es nun tatsächlich sinnvoll ist, die Bundesliga-Ergebnisse in dieser Form zu speichern, sei einmal dahingestellt, schließlich sind die beteiligten Vereine in jeder Saison andere. Sehen Sie Ganze nur als Beispiel dafür, wie sich mehrere gleichartige Arrays der Dimension k zu einem Array der Dimension k+1 zusammenschließen lassen.

 

Die Funktionen out und copy für ein drei­dimensionales int-Array lassen sich mithilfe der ent­sprechenden Versionen für ein zwei­dimensionales int-Array wie folgt schreiben:

// dreidimensionales Array ausgeben
public static void out(int[][][] a)
{
    for (int[][] x : a)
        out(x);
    System.out.println();
}

 

// dreidimensionales Array kopieren
public static int[][][] copy(int[][][] a)
{
    int n=a.length;
    int[][][] b=new int[n][][];
    for (int i=0; i<n; i++)
        b[i]=copy(a[i]);
    return b;
}

Die Funktionen zum Ausgeben und zum Kopieren von ein-, zwei- und drei­dimensionalen int-Arrays finden Sie in der Datei Array.java.

 

Weiter mit:   [Literatur]   oder   [up]

 


H.W. Lang   mail@hwlang.de   Impressum   Datenschutz
Created: 16.02.2021   Updated: 19.02.2023
Diese Webseiten sind während meiner Lehrtätigkeit an der Hochschule Flensburg entstanden