Außer der schlechten Formatierung, nichts...

Preview:

Citation preview

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

Recommended