Ein mächtiger Einkaufszettel!
Erinnerst du dich noch daran, wie du im letzten Kapitel einen Einkaufszettel in einer Liste abgespeichert hast?
Zuerst hatten wir eine ArrayList angelegt, und dann einige Gegenstände abgespeichert:
ArrayList<String> einkauf = new ArrayList<>();
einkauf.add("Salat");
einkauf.add("Tofu");
einkauf.add("Eier");
Mit
println(einkauf)
ließ sich die Liste dann ausgeben.
Jetzt ist es Zeit, dem Einkaufszettel etwas mehr Pep zu geben! Aber Achtung!
Alle werden dich um diesen Einkaufszettel beneiden… wir werden eine automatische Nummerierung mit einbauen!
Dann geht es los. Lege in einem neuen Workspace eine Datei Einkaufszettel.java an, und fange mit dieser Klasse an:
public class Einkaufszettel {
private ArrayList<String> einkauf = new ArrayList<>();
}
Als erstes brauchen wir eine Methode einkaufHinzufügen
, die einen Artikel (eine Zeichenkette) entgegennimmt, und diesen der Liste einkauf
hinzufügt. Bekommst du das hin?
Zurückgegeben werden muss nichts – wir möchten ja lediglich einen Artikel abspeichern. Mit void
liegst du also ganz richtig! Der Methodenkopf sieht also so aus:
public void einkaufHinzufügen(String artikel) {
}
Hast du darauf geachtet, dass die Methode innerhalb der geschweiften Klammern der Klasse steht?
Allerdings! Die geschweiften Klammern werden vom Computer als zusammengehöriger Block verstanden. Eine Methode außerhalb der Klasse, in der sie eigentlich stehen sollte, kann also in Java gar nicht angesprochen werden. (IDEs zeigen dann Fehlermeldungen an – manchmal allerdings nicht die, die du erwarten würdest.)
Dann kann es weitergehen. Wir müssen den Artikel, der der Methode übergeben wird, nun in der Liste einkauf
abspeichern.
Dazu reicht uns eine Zeile. Mit this.einkauf
können wir ja auf die ArrayList zugreifen, und die Methode add
fügt ein Element hinten an der Liste an:
public void einkaufHinzufügen(String artikel) {
this.einkauf.add(artikel);
}
Damit ist die Methode fertig!
Außerdem schreiben wir eine Methode druckeListe
zum drucken der Liste, in der wir die erweiterte for-Wiederholung nutzen. Kommst du damit klar?
Der Methodenkopf ist diesmal noch einfacher: wir sammeln nichts ein, und geben nichts zurück:
public void druckeListe() {
}
Erinnerst du dich noch an die erweiterte for-Wiederholung?
Genau! Hier wollen wir nur den Artikel ausgeben, daher sieht unsere Methode nun insgesamt so aus:
public void druckeListe() {
for (String art : this.einkauf) {
println(art);
}
}
Gut! Dann sollte folgender Code funktionieren: (Schreibe diesen in eine neue Datei mit Namen Start.)
Einkaufszettel e = new Einkaufszettel();
e.einkaufHinzufügen("Spaghetti");
e.einkaufHinzufügen("Oliven, schwarz, entsteint");
e.einkaufHinzufügen("Thunfisch in Olivenöl");
e.druckeListe();
Führe die Datei dann aus.
Spaghetti
Oliven, schwarz, entsteint
Thunfisch in Olivenöl
Siehst du auch so eine Liste, wenn du den Code ausführst?
Begib dich auf Fehlersuche. Wenn es Fehlermeldungen gibt, lies’ sie dir genau durch. Falls das nichts hilft, überprüfe, ob du den Code genau wie in der Hilfestellung übernommen hast. Mache erst weiter, wenn sich das Programm wie gewünscht ausführen lässt.
Sehr schön!
Gut gemacht!
Nimm dir nun ein paar Minuten Zeit, und überlege, wie du eine nummerierte Liste ausgeben lassen könntest. Versuche, deine Idee in einer Methode druckeNummerierteListe
umzusetzen!
Sehr schön!
Mmh… hast du versucht, eine Variable zähler
anzulegen, und den mit zähler++
bei jedem Schleifendurchlauf hochzuzählen?
Vielleicht sieht deine Methode so aus:
public void druckeNummerierteListe() {
int zähler = 1;
for (String art : this.einkauf) {
println(zähler + ": " + art);
zähler++;
}
}
Dann hast du die dir zur Verfügung stehenden Werkzeuge gut genutzt! Allerdings werden ältere Programmierer_innen dich vielleicht auf der Straße komisch ansehen, wenn du ihnen diese Methode zeigst.
Die Wiederholung, die du verwendet hast, heißt ja erweiterte for-Wiederholung. Diese wurde in Java beispielsweise erst in Version 5.0 eingeführt – das war im Jahr 2004.
Vorher hat man sich zu Nutze gemacht, dass eine ArrayList sowieso schon durchnummeriert ist, und ist mit einer gewöhnlichen for-Wiederholung durch die Liste gegangen. (Man nennt das auch »über eine Liste iterieren«.)
Mit (in unserem Fall) einkauf.get(hierKommtDieNummerHin)
. Programmierer_innen sprechen übrigens nicht von einer Nummer, sondern von einem Index. Meistens wird für diese Index-Variable übrigens der Name i
gebraucht. (Oder j
, oder k
, falls mehrer dieser Indizes benötigt werden.)
Eine sehr gute Frage! Die Anzahl der Elemente in einer ArrayList kann ich mit der Methode size()
abfragen, also z.B. mit einkauf.size()
.
All das zusammengenommen, ließe sich das so aufschreiben:
public void druckeNummerierteListe() {
for (int i=1; i<=this.einkauf.size(); i++) {
println(i + ": " + einkauf.get(i));
}
}
Die for-Wiederholung zählt also hoch (i++
), solange der Index i
kleiner oder gleich der Länge (size()
) der Liste ist. In jedem Wiederholungsdurchlauf wird das Element mit der Nummer i
ausgegeben, zusammen mit genau diesem Index.
Dann verändere doch einmal den Code in der Start-Datei entsprechend…
Einkaufszettel e = new Einkaufszettel();
e.einkaufHinzufügen("Spaghetti");
e.einkaufHinzufügen("Oliven, schwarz, entsteint");
e.einkaufHinzufügen("Thunfisch in Olivenöl");
// Auskommentiert – wir wollen ZAHLEN sehen!
// e.druckeListe();
e.druckeNummerierteListe();
…und lass ihn laufen! (hehe)
Hast du den Code laufen lassen? Dann solltest du einen Fehler angezeigt bekommen, nämlich eine Index out of bounds-Fehlermeldung.
Diese Fehlermeldung ist so typisch und so weit verbreitet, dass du davon ausgehen kannst, dass jede ernsthafte Programmiererin und jeder ernsthafte Programmierer sie schon einmal gesehen hat. Und du gehörst nun auch dazu! Es wurde sogar ein Podcast-Format danach benannt…
Die Ursache liegt im Wesentlichen darin, dass einige Programmiersprachen (Java gehört auch dazu) bei der 0 anfangen zu zählen – daher geraten wir dann, wenn wir nach dem letzten Element fragen, aus der Liste heraus (out of bounds). Genau das sagt die Fehlermeldung.
Das hängt mit der Art und Weise zusammen, wie unsere ArrayList intern arbeitet. Ein Array ist ein zusammenhängender, reservierter Bereich im Hauptspeicher, wo die Elemente unserer Liste gespeichert werden. Der Index 0 zeigt genau auf das erste Element, der Index 1 geht ein Element weiter (zeigt also auf das zweite Element), und so weiter… (Etwas genauer werden wir das noch später behandeln.)
Du musst dir, wenn du mit Listen arbeiten möchtest, also merken, dass diese stets beim Index 0 anfangen.
Das ist richtig! Statt bis zu dem Index zu zählen, der der Länge (size
) der Liste entspricht, müssen wir vorher aufhören. Schaffst du es, diese Code-ähnliche Formulierung als richtigen Java-Code aufzuschreiben?
wiederhole für (die Startzahl i fängt bei 0 an;
solange i kleiner als die Länge der Liste einkauf ist;
bei jedem Durchgang soll i um eins erhöht werden
)
gib aus: den Wert von i, einen Doppelpunkt, das Listenelement an Position i
In Ordnung. So sieht ein korrekter Durchlauf durch eine Liste mit einer herkömmlichen for-Wiederholung aus:
public void druckeNummerierteListe() {
for (int i=0; i<this.einkauf.size(); i++) {
println(i + ": " + einkauf.get(i));
}
}
Hast du das auch so?
Sehr schön! Dann scheinst du das Hochzählen des Listenindexes verstanden zu haben!
Sieh’ dir den Unterschied genau an, und versuche festzustellen, wo du anders gedacht hast. Falls du nicht darauf kommst, frage jemand anderen nach Hilfe!
Lass nun den Code in deiner Start-Datei noch einmal laufen, es sollte nun korrekterweise…
0: Oliven, schwarz, entsteint
1: Spaghetti
2: Thunfisch in Olivenöl
…angezeigt werden.
Hast du eigentlich Hunger?
Ach so…
Vielleicht interessiert dich ein leckeres Spaghetti-Gericht? Wie du Spaghetti kochen musst, weißt du hoffentlich – zur Not steht es auf der Packung. Wenn du außerdem den Thunfisch in einen Topf tust, die Oliven in Ringe zerschneidest und dazugibst, und dann alles etwa 5 Minuten bei mittlerer Hitze warm machst, hast du eine leckere Pasta-Sauce. Guten Appetit!
Die folgenden Dinge solltest du dir merken. Schreibe sie in dein Heft – vielleicht möchtest du sie auch auf Karteikarten übertragen und wie Vokabeln lernen? So wirst du sie besser im Gedächtnis behalten können…
Neue Vokabeln in dieser Lektion
Schreibe den entsprechenden Code auf, und überprüfe, ob du richtig liegst!
Feststellen, wie viele Einträge die Liste meineListe
hat, und das Ergebnis in einer neuen Variablen länge
abspeichern.
int länge = meineListe.size();
Auf das allererste Element einer Liste meineListe
zugreifen.
meineListe.get(0);
Auf das allerletzte Element der Liste meineAndereListe
zugreifen, ohne vorher zu wissen, wie lang diese Liste ist.
meineAndereListe.get(meineAndereListe.size() - 1);
Eine (herkömmliche) for-Wiederholung verwenden, um über meineListe
zu iterieren und bei jeder Wiederholung das Listenelement mit println
ausgeben.
for (int i=0; i<meineListe.size(); i++) {
println(meineListe.get(i));
}