außer der schlechten formatierung, nichts...
TRANSCRIPT
427
428
Außer der schlechten Formatierung, nichts Neues.
429
430
431
432
Der String-Vergleich mit ==, obwohl man nur inhaltliche Gleichheit haben möchte, ist ein sehr typischer und leider auch schwer zu entdeckender Programmierfehler. In ganz seltenen Fällen kann es passieren, dass eine Lösung mit == trotzdem funktioniert, bei einer späteren Nutzung, z. B. mit einer aktualisierten Java-Version, aber nicht funktioniert. Der Java-Standard definiert nur, wann == in diesem Fall true ergeben muss.
Das Beispiel zeigt, dass die Klasse String, wie fast alle Java-Klassen die equals-Methode der Klasse Object überschreibt.
433
Man beachte, dass hier die equals-Methode der Klasse Object genutzt wird, die nur auf Identität prüft
434
435
Die Methode remove(Object) soll das erste Vorkommen des übergebenen Objekts löschen. Bei der Prüfung auf "vorkommen" wird die Methode equalsgenutzt, die für die Klasse Punkt noch nicht neugeschrieben wurde.
Deshalb hat der erste remove-Befehl keinen Effekt, da es keinen Punkt gibt, der identisch zum gerade angelegten Punkt ist.
436
Man erkennt, dass statt der Klasse Boolean als Rückgabetyp boolean genutzt wird. Bis zur weiteren Betrachtung von boolean (und int statt Integer) werden beide Bezeichnungen etwas zu vereinfachend als gleichwertig angesehen.
Hier wird vereinfachend angenommen, dass weder this.x noch this.y null sein können.
437
Man vergleicht typischerweise nicht alle Objektvariablen, wenn es einen eindeutig identifizierenden Wert, wie die Matrikelnummer, gibt. Werden z. B. Daten aus verschiedenen Quellen zusammenkopiert, reicht es dann aus, dass die identifizierenden Werte übereinstimmen. Tippfehler bei Namen oder Änderungen z. B. durch Heirat, müssen dann nicht in allen Datenbeständen nachgepflegt werden.
438
439
440
441
442
443
444
Das "fast" in Klammern deutet darauf hin, dass es in bestimmten Fällen notwendig ist, die Methode hashCode() zu überschreiben. Dies wird etwas später mit einem Beispiel gezeigt.
445
Es sei daran erinnert, dass beim Zusammenbau des Strings in toStringautomatisch die toString-Methoden von start und ende aufgerufen werden. Alternativ hätte man auch this.start.toString() und this.ende.toString() nutzen können und würde zum gleichen Ergebnis kommen.
446
447
448
449
Die blasseren Anteile sind noch kurzzeitig im Speicher. Da aber keine Variablen diese Speicherbereiche referenzieren, werden sie später durch Java, genauer vom Garbage Collector der Java Virtual Machine, gelöscht.
450
451
452
453
454
Dies ist kein Aktivitätsdiagramm, sondern ein Entscheidungsdiagramm. Generell muss man sich bei jeder Objektsammlung fragen, welchen Typen sie hat. Wählt man den falschen Typen, kann die Implementierung unnötig komplex und fehleranfällig sein. Möchte man z. B. keine doppelten Objekte, so ist dies mit einer ArrayList deutlich aufwändiger als mit einer HashSet zu realisieren. Die verschiedenen Klassenvarianten in den Blättern deuten wiederum an, dass es für verschiedene Rahmenbedingungen, wie die Größe der Datensätze und die Häufigkeit des Lesens und Schreibens effiziente und nicht so effiziente Implementierungen gibt. Einen Einblick gibt die Vorlesung "Algorithmen und Datenstrukturen".
Die erwähnte Sammlung Bag ist nicht Teil der Java-Klassenbibliothek. Dafür stehen aber weiter Bibliotheken zur Verfügung, von denen einige auch frei im Internet erhältlich sind.
455
Nutzt man die Klasse HashSet direkt mit einer Klasse, die die hier wichtige Methode hashCode() der Klasse Object nicht überschreibt, steht das erwartete Verhalten nicht zur Verfügung. Erwartet wird, dass man bzgl. equals() gleiche Objekte nur einmal hinzufügen kann. Obwohl die Klasse Punkt die Methode equals ordentlich überschreibt, tritt trotzdem das Problem auf.
456
Die Methode hashCode() ist in der Klasse Object realisiert und wird hier aufgerufen.
Die generelle Idee ist, dass das Aufruf von equals recht lange dauern kann, da man alle Objektvariablen und evtl. deren Objektvariablen durchlaufen muss. Um dies zu verkürzen gibt es die Idee, die hashCode-Methode zu nutzen, mit der für ein Objekt recht schnell ein int-wert (vergleichbar zum Integer-Wert) berechnet wird. Bei Objekten, die diese Gleichheitsprüfung nutzen, erfolgt diese zweistufig. Zunächst wird die Gleichheit der hashCode-Ergebnisse geprüft und nur, wenn diese gleich sind, wird equals durchgeführt.
Überschreibt man die gashCode-Methode nicht, ist diese zwei Objekte, auch mit gleichen Werten der Objektvariablen, typischerweise nicht gleich.
457
Leider muss an dieser Stelle der Datentyp int als Rückgabetyp stehen, er kann nicht durch Integer ersetzt werden. Was "int" eigentlich ist, wird etwas später erklärt.
Es gibt verschiedene Ansätze für möglichst schnell berechenbare Hash-Funktionen die für unterschiedliche Objekte möglichst oft unterschiedliche Werte liefern. Das Thema wird hier nicht weiter vertieft. Eine plumpe Lösung wäre es eine hashCode()-Methode zu Schreiben, die immer die Zahl null zurückliefert. Damit würde immer sichergestellt, dass die equals-Methode zum Vergleich genutzt wird.
458
459
460
Das Beispiel zeigt mit wo1 die Möglichkeit der direkten Initialisierung, die auch die Array-Größe auf sieben festlegt. Mit wo2 wird gezeigt, dass es auch einen Konstruktor für Arrays mit einer etwas besonderen Syntax gibt, die auch die Array-Größe festlegt. Durch diese Objekt-Erstellung haben alle Array-Elemente den Wert null. Man kann auch Variablen vom Typ Array deklarieren und ihnen später passende Arrays zuweisen. Eine direkte Initialisierung mit Werten ist dabei allerdings nicht möglich.
Arrays können natürlich auch Typen von lokalen Variablen sein.
Die beiden Schreibweisen String[] wo1 und String wo1[] sind bei äquivalent, können also beide in genau gleicher Form genutzt werden. Die erste Schreibweise hat den wesentlichen Vorteil, dass man den Typ der Variablen klar vom Namen der Variablen getrennt hat.
461
Die Methode kommtNichtVor(Kugel, i) prüft, ob der Wert kugel im Array werte bis zur Position i-1 vorkommt. Falls der wert bereits vorkommt, also der Wert bereits gezogen wurde, passiert nichts und im neuen Schleifendurchlauf wird wieder eine "Kugel" gezogen. Insgesamt können so sechs verschiedene Werte gezogen und den Array werte geschrieben werden.
462
Die Methode kommtNichtVor bekommt einen zu suchenden Wert wert und eine Position übergeben, bis zu welcher Position der Wert in dem Array von 0 an startend gesucht werden soll. Die Beschränkung auf die position ist notwendig, damit nur bisher gefüllte Felder angesehen werden.
463
Arrays haben selber keine sinnvolle toString()-Methode, so dass man diese selber schreiben muss. Der vorgestellte Ansatz ist recht langsam, da immer wieder neue String-Objekte aufgebaut werden. In der Praxis würde man hierfür eher Klassen wie StringBuffer nutzen.
464
Die die Methode gemeinsam wird einem Tipp-Objekt ein zweites Tipp-Objekt tipübergeben. Es werden dann alle Werte der beiden Tipps verglichen und alle Übereinstimmungen gezählt.
465
Bei diesen Testfällen ist die Frage, wer testet den Tester, durchaus zu stellen. Man kann in dieser Klasse auch Tests der Hilfsmethode unterschiedlich(.) ergänzen. Der Testfall überprüft, ob in den zufällig erstellten Tests garantiert nur unterschiedliche Werte zwischen 1 und 49 eingetragen sind.
Tests der Methode enthaelt() sollten weiterhin noch ergänzt werden.
466
Die Tests zeigen eine Variante der Array-Erzeugung, wenn dieser als Parameter übergeben werden soll. Es ist nicht möglich, hier nur den Array hinzuschreiben.
467
In der Variablen ergebnis[] stehen später die Anzahlen von keiner, einer, zwei, drei, vier, fünf und sechs Übereinstimmungen, deshalb wird ein Array mit sieben Elementen genutzt, deren werte auf 0 gesetzt werden.
468
469
470
Wenn man z. B. mehrere Strings zusammen verwalten will, kann man kurz darüber nachdenken, diese zeilenweise in einem Array zu verwalten. Dies soll vermieden werden, da die Grundregel gilt, dass zusammengehörige Daten in einem Objekt zusammengefasst sein sollen.
471
In mehrdimensionalen Arrays kann jedes Teilarray eine unterschiedliche Länge haben, die immer mit .length abgefragt werden kann.
472
473
474
475
476
Auf dieser und den beiden folgenden Folien wurde jeweils ein neues Objekt der Klasse FigurMalerei erstellt und die angegebene Methode ausgeführt.
477
478
479
480
481
482
483
484
Die verkürzte Überschrift soll andeuten, dass hier die Probleme mit möglichen null-Werten nicht betrachtet werden. Wichtig ist allerdings, dass es eine equals-und ein hashCode-Methode gibt.
485
Die verkürzte Überschrift soll andeuten, dass hier die Probleme mit möglichen null-Werten nicht betrachtet werden. Wichtig ist allerdings, dass es eine equals-und ein hashCode-Methode gibt.
486
487
488
489
Mit der Methode values() erhält man eine Sammlung von allen Value-Objekten, die sich aktuell in dem HashMap-Objekt befinden. Die Berechnung dieses Ergebnisses ist sehr aufwändig. Wenn diese Methode häufiger im Programm steht, viel wichtiger aber häufig im laufenden Programm genutzt wird, sollte man über die Nutzung einer anderen Sammlung nachdenken.
Die Methode remove liefert als Ergebnis das gelöschte Value-Objekt. Falls kein Objekt an der angegebenen Key-Position gefunden wurde, ist das Ergebnis null. Man beachte, dass bei dieser Methode vorher eine Schleife notwendig war, auf die jetzt verzichtet werden kann.
490
491
492
493