Hilfe bei Java Hashmap 10. Klasse?

3 Antworten

Hey, um eine Hash-Map zu erklären würde ich eine eigene HashMap implementieren. Wie wäre das? :D

Eine HashMap kann mehrere Objekte aufnehmen. Dazu wird zu jedem Objekt ein Hash erstellt und das Objekt dann entsprechend dem Hash im Speicher abgelegt.
Der Vorteil ist dann das Abrufen. Möchte ma ein Objekt aus der Hashmap kann man anhand des Hashes direkt auf den Speicher zugreifen und muss nicht erst über alle möglichen Elemente interieren.

Damit Kollisionen vermieden werden, falls zwei Objekte doch mal den selben Hash haben, wird das Objekt meist nicht direkt abgelegt, sondern eine Liste an der Stelle, welche dann alle Objekte mit dem selben Hash aufnimmt. Dort muss dann doch wieder interativ gesucht werden.
Alternativ, so meine ich, gibt es auch Implementierungen welche die HashFunktion wiederholt aufrufen, bis ein freier Speicherplatz "gefunden" wurde.

Ein einfaches Beispiel einer Hashfunktion wäre Modulo zu rechnen, also Ganzzahlige Division und davon der Rest.

Du hast dann ein Array mit 10 Elementen und rechnest bei deinem Objekt modulo 10. Das Ergebnis ist die Indexposition an die dein Objekt gehört. Damit Du überhaupt etwas rechnen kannst musst Du dein Objekt irgendwie als Zahl repräsentieren, dafür implementierst Du dir zum Beispiel eine hash Methode in deinem Objekt.
Du kannst zum Beispiel String Attribute in Zahlen umwandeln. Zahlen im Objekt selbst und sonstige Informationen nutzen um eine einzelne Zahl zu ermitteln, die Du dann modulo rechnest :D

Wenn Du etwas weiter gehen möchtest kannst Du in dein Array dann Listen von Objekten hängen um die angesprochenen Kollisionen zu vermeiden. Oder aber Du wirst eine Exception um zu signalisieren, dass dein Array bereits belegt ist.

Wenn Du nun prüfen willst ob ein Objekt bereits in deiner HashMap ist, dann kannst Du einfach den Hash deines Objekts berechnen und dann an entsprechender Stelle im Array direkt nachsehen. Du musst also nicht mehr das gesamte Array durchsuchen.

Das wäre eine ganz einfache und trotzdem performante Implementierung. Natürlich kannst Du das beliebig aufbohren und verbessern. Um die Grundlagen zu erklären wird es mehr als reichen.

Gruß

Bilguun775 
Fragesteller
 01.06.2021, 20:34

Danke für Deine ausführliche Nachricht, aber ich verstehe irgendwie nichts in der Nachricht, da unser Lehrer uns nichts dazu beigebracht hat und ich einen Großteil der Begriffe nicht verstehe. Gibt es online irgendwo einen Code der zum implementieren einer Hashmap passt, den ich so ähnlich benutzen könnte?

0
AldoradoXYZ  01.06.2021, 20:44
@Bilguun775

Hey,

sollst Du denn selbst eine HashMap implementieren, also die Innereien.

Oder sollst Du, wie gogogo vorschlägt, eine HashMap einfach benutzen?
HashMap (bzw. Map allgemein) bringt Java standardmäßig mit.

Gruß

0
Bilguun775 
Fragesteller
 01.06.2021, 20:48
@AldoradoXYZ

"Ihr sollt das Thema/die Aufgabe aus der Liste unten in Java

programmieren und mit einem Text erklären. Der Code soll dabei gut

verständlich sein, denn er ist für andere Schüler:innen gedacht"

"(Ihr sollt "Eure" Java-Anweisung selber erklären und einige konkrete

Java-Beispiele geben. Umfang ca. 3 A4-Seiten. Abgabeformat: Word)"

Ich glaube den Code dann beschrieben, also was er macht und dann jede einzelne Zeile beschreiben. Ich kenne mich mit Java nähmlich garnicht aus, also will ich das so einfach wie möglich machen.

0
AldoradoXYZ  01.06.2021, 20:50
@Bilguun775

Okay, und was für eine Aufgabe steht da genau in der Liste? Also der Wortlaut der Aufgabe die Du machen möchtest :)

Es macht einen Unterschied ob da steht:
"Nutze eine HashMap und erkläre wie dein Programm funktionniert."

oder

"Implementiere eine eigene HashMap und erkläre wie sie funktioniert."

Gruß

0
Bilguun775 
Fragesteller
 01.06.2021, 20:55
@AldoradoXYZ

Da steht nur "Nr.13 (mein Name) Hashmap".

Dieser Lehrer ist an unserer Schule bekannt, viel von uns zu erwarten, was wir noch nie gemacht haben und müssen dies dann selbstständig machen. Schreibe am Freitag auch eine Arbeit über die Udacity-Kurse und alles was wir bis jetzt gemacht haben hat so gut wie nichts miteinander zu tun.

0
AldoradoXYZ  01.06.2021, 20:58
@Bilguun775

Du, ich würde so eine Aufgabe so interepretieren, dass Du eine HashMap benutzen sollst.

Um etwas sicherer zu sein, kannst Du die "anderen Aufgaben" noch hinschreiben?

Vermutlich sowas wie LinkedList, ArrayList, Set.

Gib mir etwas, ich schreibe dir ein einfaches Beispiel :D

Schüler in einer HashMap, wie klingt das?

Gruß

0
Bilguun775 
Fragesteller
 01.06.2021, 20:59
@AldoradoXYZ

Also meinst Du die anderen zugeordneten Themen meiner Klassenkameraden?

0
Bilguun775 
Fragesteller
 01.06.2021, 21:20
@AldoradoXYZ

ich hoffe einfach, dass du die Themen meinst und ich entferne die Namen zur Sicherheit.

1       Die math-Bibliothek

2    Rekursive Berechnung der „Fakultät“

3     Bestimmung des Medians in einem Array

4        Exceptions

5      Verschachtelte schleifen & 2dim-Arrays

6       Datum und Uhrzeit

7       Printf-Funktion

8        Collections

9          Einfach verkette Listen in Java

10      Doppelt verkettete Listen in Java

11     Datenstruktur Stack

12     Hashtable

13    Hashmap

        Iterator

15   r Die Exponentialdarstellung 10e-3 in Java

16    Beispiele für Rundungsfehler

17     Methoden mit Parametern

18    Einlesen von der Tastatur

0
AldoradoXYZ  01.06.2021, 21:29
@AldoradoXYZ

Fangen wir mit einer Klasse für Schüler an, die wir in eine HashMap packen wollen:

package hashmap;

public class Pupil {

    private String name;

    private int age;

    public Pupil(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public String toString() {
        return "[Name: "+name+" Alter: "+age+"]";
    }

    @Override
    public boolean equals(Object other) {
        System.out.println("\tEquals wurde aufgerufen auf: " + this.toString() + " mit " + other.toString());
        if (this == other) {
            System.out.println("\t\tBeide sind gleich");
            return true;
        }

        if (other == null || getClass() != other.getClass()) {
            System.out.println("\t\tBeide sind nicht gleich");
            return false;
        }

        Pupil pupil = (Pupil) other;
        boolean result = age == pupil.age &&
                name.equals(pupil.name);

        if (result == true) {
            System.out.println("\t\tBeide sind gleich");
        } else {
            System.out.println("\t\tBeide sind nicht gleich");
        }

        return result;
    }
}

Dazu dann noch eine Test-Klasse um das auszuprobieren:

package hashmap;

import java.util.HashMap;
import java.util.Map;

public class Main {
    public static void main(String[] args) {
        new Main();
    }

    public Main() {
        Map<String, Pupil> pupils = new HashMap<>();

        Pupil paul = new Pupil("Paul", 12);
        Pupil paul2 = new Pupil("Paul", 13);
        Pupil lisa = new Pupil("Lisa", 13);
        Pupil hanz = new Pupil("Hanz", 12);

        pupils.put(paul.getName(), paul);
        pupils.put(paul2.getName(), paul2);
        pupils.put(lisa.getName(), lisa);
        pupils.put(hanz.getName(), hanz);
        System.out.println("Gibt den Key Paul in der HashMap? " +  pupils.containsKey("Paul"));
        System.out.println("Gibt den Key Tim in der HashMap? " +  pupils.containsKey("Tim"));

        System.out.println("\n");

        Pupil resultPupil = pupils.get("Paul");
        System.out.println("In der HashMap wurde unter 'Paul' ein Schüler gefunden: "+resultPupil.getName()+" Alter: "+resultPupil.getAge());

        System.out.println("\n");

        System.out.println("pupils.containsValue(hanz) aufgerufen");
        boolean containsHanz = pupils.containsValue(hanz);
        System.out.println(hanz.toString()+" ist noch in der HashMap enthalten. containsHanz ist "+containsHanz);

        System.out.println("\n");

        System.out.println("pupils.containsValue(paul) aufgerufen");
        boolean containsPaul = pupils.containsValue(paul);
        System.out.println(hanz.toString()+" ist nicht mehr in der HashMap enthalten, da das Objekt mit paul2 überschrieben wurde. containsPaul ist "+containsPaul);
    }
}

Die Ausgabe ist dann:

Gibt den Key Paul in der HashMap? true
Gibt den Key Tim in der HashMap? false

In der HashMap wurde unter 'Paul' ein Schüler gefunden: Paul Alter: 13

pupils.containsValue(hanz) aufgerufen
[Name: Hanz Alter: 12] ist noch in der HashMap enthalten. containsHans ist true




pupils.containsValue(paul) aufgerufen
	Equals wurde aufgerufen auf: [Name: Paul Alter: 12] mit [Name: Hanz Alter: 12]
		Beide sind nicht gleich
	Equals wurde aufgerufen auf: [Name: Paul Alter: 12] mit [Name: Paul Alter: 13]
		Beide sind nicht gleich
	Equals wurde aufgerufen auf: [Name: Paul Alter: 12] mit [Name: Lisa Alter: 13]
		Beide sind nicht gleich
[Name: Hanz Alter: 12] ist nicht mehr in der HashMap enthalten, da das Objekt mit paul2 überschrieben wurde. containsPaul ist false

Ich habe mal einfach ein paar System.out.println in den Code eingefügt um den Ablauf ohne Debugger klar zu machen.

Im Grunde wird bei einer HashMap<String, Pupil> unter dem Schlüssel, hier String, nämlich der Name, ein Schüler (Pupil) abgelegt.
Das machst Du in dem Fall mit pupils.put(paul.getName(), paul)

An den Ausgaben siehst Du, dass paul2 allerdings unseren paul überschreibt, da beide den selben Namen besitzen und damit gibt die verwendete HashFunktion auf String den selben Wert zurück.
An der Stelle würde ich erwähnen, dass doppelte Schlüssel nicht möglich sind und das erste Objekt "verdrängt" wird. Auf Hashing und die innere Arbeitsweise würde ich bei der Aufagabe, vorallem als Anfänger, nicht eingehen.

Gruß

0
Bilguun775 
Fragesteller
 01.06.2021, 21:46
@AldoradoXYZ

Okay vielen Dank für Deine Mühe, ich glaube ich verstehe das gesamte Thema einfach nicht ganz aber ich versuche diesen Code zu verstehen und speicher den(screenshot). Ich spreche einfach nochmal mit meinem Lehrer. Nochmals danke :)

0
AldoradoXYZ  01.06.2021, 23:16
@Bilguun775

Du kannst den Quelltext kopieren, kein Grund für einen Screenshot.

Was die Themenliste angeht, das ist schon etwas fortgeschritten und nicht mehr blutiges Anfängerniveau. Ich meine HashMap, mehrfach verkettete Listen, Rekusion um die Fakultät zu berechnen.

Auf der anderen Seite machen Lehrer das ja ganz gerne mal, jeder bekommt ein Thema und soll es den anderen erklären. Die Hoffnung ist, dass möglichst viele Themen möglichst schnell und gut gelernt werden.

Gruß

0
Bilguun775 
Fragesteller
 02.06.2021, 23:35
@AldoradoXYZ

Hey ich bins nochmal, also ich hab mit meinem Lehrer geredet und ihm gesagt, dass ich es einfach nicht verstehe, daraufhin hat er mir ein neues Thema gegeben. "Java Dateien/Files - String in Datei speichern und String aus Datei lesen". Ich habe jetzt verstanden was ein String ist und die Regeln dazu. Zum Speichern eines Strings in der Datei verstehe ich nicht ganz, welche Befehle man anwenden sollte, doch bei dem Auslesen eines Strings muss Files.readString anwenden oder?

Wir haben im Unterricht einen Code besprochen den ich auch verstanden habe und beschreiben kann(Würde gerne ein Bild hinzufügen aber es klappt net). Ich soll jetzt für das Speichern und Auslesen jeweils einen Code machen und jede Zeile beschreiben können. Könntest Du mir vllt so einen passenden, möglichst einfachen Code erstellen? Würde mir extrem helfen.

Danke

0
AldoradoXYZ  03.06.2021, 13:08
@Bilguun775

Hey, keine Bilder einfügen, kopiere den Quellcode, den Text :)

Wenn Du hier eine Antwort postest gibt es sogar (oben rechts bei der Antwort) einen Button für Formatierungsoptionen und dort findest Du sogar Quelltext. Dann sieht dein Code sogar gut aus :D

guck:

public static void main(String[] args) {
    System.out.println("hallo Welt");
} 

cool oder?

Gruß

0
Bilguun775 
Fragesteller
 03.06.2021, 14:29
@AldoradoXYZ
Danke, aber ich habe nur ein Screenshot von den Code gemacht, da es online war.
0
AldoradoXYZ  03.06.2021, 14:33
@Bilguun775

Dann eine neue Frage :D

Bei neuen Fragen kann man Bilder einfügen

...immer diese technischen Begrenzungen

Gruß

0

Werde von List über Set und Map zur HashMap kommen.

Eine List ist das Interface für eine Sammlung von Elementen einer festgelegten Klasse mit Reihenfolge. Man kann

  1. Anzahl der Elemente
  2. Gib mir Element an Position _n_
  3. Gibt es ein Element das identisch ist mit meinem Element _inst_

aufrufen. Wenn ich eine Liste mit 10 Elementen habe, die alle verschieden sind, so muss die Liste jeweils unterschiedlich weit durchlaufen werden und ein Vergleich auf Gleichheit durchgeführt werden. Bei den 10 Elementen sind das 55 Vergleiche.

Aber bei 100 Elementen schon 5050, bei 1000 Elementen schon 500500 etc.

Wie man sieht geht die Anzahl der Vergleiche bei Faktor 10 für die Länge mit Faktor 100 = 10². Das nennt man eine Komplxität von o(n²).

Das ist nicht schön. Daher hat man nach besseren Lösungen gesucht. Die bekannteste ist das Arbeiten mit Hashes. Ein Hash ist meist ein Zahlenwert, so auch in Java. Um mit Hashes in Java arbeiten zu können, braucht man die Umsetzung eines Elements der speichernden Klasse in einen int.

Dazu ist die Methode hashCode() aus der Klasse Object da. Object ist die oberste Elternklasse einer jeden Klasse in Java.

Ganz wichtig: du musst die Methode auch in deiner Klasse noch selbst hinschreiben und mit einem sinnvollen Code füllen.

Ich mache mal ein Beispiel mit String:

"rot" -> 43

"grün" -> 82

"blau" -> 39

"orange" -> 50

"Orange" -> 97

"grau" -> 12

"schwarz" -> 66

"gelb" -> 74

Jetzt mache ich 10 einzelne Listen für 8 Werte. Gerne ein paar mehr als Anzahl der Werte. Jedes Element wird bezüglich seines HashWertes modulo 10, also der hinteren Ziffer in die entsprechende Liste einsortiert.

0: orange

1:

2: grün, grau

3: rot

4: gelb

5:

6: schwarz

7: Orange

8:

9: blau

Wenn jetzt alle 8 einmal gesucht werden sollen, so sind nur 9 statt 36 Vergleiche notwendig.

Zum Suchen muss Java aber wissen, ob zwei beliebige Objekte für Dich als gleich gelten sollen. Sonst kann Java das nicht feststellen. Dazu musst du equals() aus Object in deiner Klasse überschreiben.

Sets: sind wie Listen, aber ohne Sortierung. Jedes Element von dir kann nur einmal aufgenommen werden. Dazu wird ebenfalls equals() benötigt. Du kannst zufügen / löschen und prüfen, ob ein Element von Dir im Set ist.

Zur schnellen Suche sind auch hier Hashes sinnvoll.

Maps: wie Sets, nur dass zu jedem Element eines Sets noch ein Datenobjekt dazugehört.

Du hast Keys von der ersten Klasse zum Suchen in der Map und wenn es bei einer Suche einen Treffer gibt, dann bekommst du den Value, den zweiten Typ der Map.

Auch hier ist es sinnvoll, schnell den Eintrag finden zu können und deshalb das Hashing einzusetzen.

Noch Fragen?

Bilguun775 
Fragesteller
 03.06.2021, 22:18

Oh tut mir Leid ich habe Deine Antworten nicht gesehen und wollte mich bedanken. Ich habe mittlerweile ein neues Thema, könntest Du dir vielleicht meine neuste Frage angucken, weil ich nichts zum speichern eines Strings in einer Datei finde, falls Dir aber noch was hilfreiches einfällt, würde ich mich freuende.

Vielen Dank

1
gogogo  04.06.2021, 16:36
@Bilguun775

Mache ich gleich.

Hast du meine zweite Antwort zu Hashes verstanden?

0

Das wichtigste ist die Methode hashCode().

Nimm die Klasse Integer und baue dazu eine eigene Klasse MyInteger ohne Überschreiben der Methode hashCode(). Integer hat die Methode überschrieben.

MyInteger hat ein Element vom Typ int, das vom Konstruktor gesetzt wird.

Nun hast du Map<Integer, String> und Map<MyInteger, String>, die beide als HashMap realisiert sind.

Beide füllst du mit Paaren wie <3, "drei"> und anschließend suchst du per Integer-Wert nach den Werten. Einige wirst du bei MyInteger nicht finden.

AldoradoXYZ  01.06.2021, 20:28

Hey, das Problem bei deinem Ansatz: Er benutzt damit zwar eine Map, aber erklärt in keiner Weise was das ist, oder wie sie funktioniert - also intern.

Gruß

0
gogogo  01.06.2021, 20:38
@AldoradoXYZ

Habe mich auf den Teil "... Idee was man für einen Code machen könnte" der Frage konzentriert.

Vom SmartPhone die ganze HashMap zu beschreiben ist mir zu aufwändig.

Dazu hätte ich erst beim HashSet angefangen zu erklären. Dann wird es für den Fragesteller sicherlich einfacher.

0
AldoradoXYZ  01.06.2021, 20:45
@gogogo

Ah Handy, okay.

Evtl. kannst Du meine Antwort lesen und hast da noch Vorschläge, Korrekturen, Verbesserungen. Das geht vielleicht mit weniger Text.

Gruß

1
gogogo  01.06.2021, 21:21
@AldoradoXYZ

Versuche morgen, HashCollections mal mit meinen Worten darzustellen. Jetzt fehlt die Zeit.

0
gogogo  02.06.2021, 18:24
@AldoradoXYZ

Habe nun noch eine ausführliche Antwort zu Hashes und deren Sinn geschrieben.

Drei Fehler sind in deiner Antwort:

- der HashCode ist zu der Key-Klasse mit int hashCode() zu überschreiben

- die hashCode() Methode muss bei mehrmaligen Aufruf auf ein unverändertes Objekt immer den selben Rückgabewert haben. Also deterministisch sein

- es gibt keine Exception bei einer Kollision von Hashes. Dann sind halt mehrere Keys in der Liste.

0
AldoradoXYZ  02.06.2021, 19:09
@gogogo
der HashCode ist zu der Key-Klasse mit int hashCode() zu überschreiben

Wie Du schon selbst sagst "überschreiben". Object bringt hashCode bereits mit. Man muss nicht überschreiben, sollte es aber.
Generell sollte man equals und hashCode überschreiben. Ansonsten gilt, wenn man equals überschreibt, dann auf jeden Fall hashCode. Man kann aber auch nur hashCode überschreiben und equals nicht xD
Aber ja, überschreib alles

die hashCode() Methode muss bei mehrmaligen Aufruf auf ein unverändertes Objekt immer den selben Rückgabewert haben. Also deterministisch sein

Genau genommen muss die hashCode den selben Rückgabewert für Objekte liefern die equals() == true liefern.

- es gibt keine Exception bei einer Kollision von Hashes. Dann sind halt mehrere Keys in der Liste.

java.util.HashMap arbeitet mit Verdrängung, dort gibt es keine extra Liste. Die Exception ist nur ein Vorschlag, man kann natürlich auch anders damit umgehen, wenn man eine eigene Implementierung macht und die hängt vom gewünschten Ergebnis ab.

Danke für die Hinweise.

Gruß

1
gogogo  02.06.2021, 19:26
@AldoradoXYZ

Wenn man equals() nicht überschreibt bei Containern, wird einiges schief laufen und der Fehler ist schwer zu finden. Die Funktion von Set (ist Element enthalten?) baut elementar darauf auf.

Java kann dann die Gleichheit nicht feststellen, nur auf 'das selbe'.

Sonst stimme ich dir zu.

0
gogogo  02.06.2021, 19:34
@AldoradoXYZ

Es liegt meist an der JavaVirtualMachine, was equals() und hashCode() zurückliefern, wenn die nicht überschrieben sind. Definiert ist nichts.

Das ist in dem Buch für meine Oracle Java 6 Prüfung so beschrieben.

0
AldoradoXYZ  02.06.2021, 19:40
@gogogo

Also equals ist Standardmäßig so in Object implementiert:

public boolean equals(Object obj) {
    return (this == obj);
}

HashCode je nach JVM, in meinem Fall bekomme ich wunderbare Integer-Werte zurück xD

Aber ja, überschreib alles um safe zu sein. Ich sage nicht, dass man das nicht soll. Generell schreibt man eh Tests die alles wasserdicht machen. Duplikate sind ja gern mal ein Fehler.

Gruß

1