# HashMap Probleme



## Eva (4. Mai 2004)

Hallo Leute, 

ich hab ein Problem und weiß nicht, warum das so ist: 

Ich habe für eine Übung zwei Klassen "Person" und "Lehrveranstaltung" implementiert und zusätzlich eine Klasse "VirtualDataBase", in der ich eine "HashMap" angelegt habe. In dieser HashMap möchte ich als Schlüssel die Objekte der Klasse Person einfügen und als zweite Komponente der HashMap ist ein Vektor vorhanden, der die Lehrveranstaltungen zu der Person speichert. 

Das Problem, dass ich jetzt habe ist, das ich die Komponenten nicht mehr erreiche. Das heißt, wenn ich in der Hashmap nach einem Schlüssel suche und von diesem den Vektor haben möchte, bekomme ich immer null heraus, obwohl GANZ SICHER Daten vorhanden sind. 

Bei folgendem Codestück (Methode der Klasse VirtualDataBase) bekomme ich immer null heraus, obwohl die Daten sicher vorhanden sind: 

  public int getNumberOfLecture (Student s) {
      Vector vec = (Vector) studentHashMap.get(s);   
      if (vec == null) 
        return 0;	
      return vec.size();
  }//getNumberLecture

Wo kann der Fehler liegen? Kann es sein, dass ich noch zusätzlich Methoden implementieren muss? Ich habe in der Klasse Person die Methode hashCode() überschrieben, dass doch reichen sollte?!

Danke für eure Hilfe, 

Eva


----------



## Thomas Darimont (4. Mai 2004)

Hallo!

Dein Problem wird sein, dass du bei deinen Klassen die Methoden 
int hashCode() und  boolean equals(Object o) überschreiben musst...

diese beiden Konstrukte werden nämlich von der Hashtable verwendet um zu einem Schlüssel den Wert zu finden ...

Gruß Tom


----------



## Eva (4. Mai 2004)

Die beiden Methoden habe ich überschrieben!
Die Methode hashCode() retuniert einen neuen Code, der aus den Datenkomponenten generiert wurde und equals(Object o) vergleicht die Objekte miteinander. 
Ist aber bei diesen beiden Methoden auf etwas besonderes zu achten

Eva


----------



## Thomas Darimont (4. Mai 2004)

Hallo!

Hmmm, wie legst du denn die Elemente in die Hashmap ...?

Gruß Tom


----------



## Eva (4. Mai 2004)

Ich habe mal ein Objekt Person und Objekte von Lehrveranstaltung: 

  Person p0 = new Person("sem02010", "Eva" , "Langegger");
  Lecture l0 = new Lecture("Programming");

Dann speichere ich die Person als Key und generiere einen neuen Vektor. Danach hole ich mir den Vector und füge die Lehrveranstaltungen ein (als Beispiel nur ein Eintrag): 

  studentHashMap.put(p0, new Vector());
  Vector vec0 = (Vector) studentHashMap.get(p0); 
  vec0.add(l0); 

So generiere ich mir die HashMap! Es sind aber die Elemente sicher vorhanden, weil beim Debuggen kann ich sie mir angucken. 

LG 
  Eva


----------



## Thomas Darimont (4. Mai 2004)

Hallo!

Vielleicht hilft dir das Beispiel hier weiter:


```
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/*
 * Created on 04.05.2004
 */

/**
 * @author Thomas Darimont
 */
public class HashtableTest {

	public static void main(String[] args) {
		new HashtableTest().testIt();
	}

	/**
	 * 
	 */
	private void testIt() {

		HashMap map = new HashMap();

		Student tom = new Student("Darimont", "Thomas", 122342);

		List lectureList = new ArrayList();

		Lecture lecture0 = new Lecture("Programmierung");
		Lecture lecture1 = new Lecture("Analysis");
		Lecture lecture2 = new Lecture("Consulting");

		lectureList.add(lecture0);
		lectureList.add(lecture1);
		lectureList.add(lecture2);

		map.put(tom, lectureList);

		//..........

		List list = (List) map.get(tom);

		Object[] items = list.toArray();
		for (int i = 0; i < items.length; i++) {
			System.out.println(((Lecture) items[i]).getName());
		}

	}

	class Student {
		private int hashCode;
		private String vorname;
		private String nachname;
		private int matrikelNr;

		public Student(String name, String vname, int matNr) {
			nachname = name;
			vorname = vname;
			matrikelNr = matNr;
		}

		public int hashCode() {
			if (hashCode == 0) {
				hashCode = (matrikelNr + vorname + nachname).hashCode();
			}
			return hashCode;
		}

		/**
		 * @return
		 */
		public int getMatrikelNr() {
			return matrikelNr;
		}

		/**
		 * @return
		 */
		public String getNachname() {
			return nachname;
		}

		/**
		 * @return
		 */
		public String getVorname() {
			return vorname;
		}

		/**
		 * @param i
		 */
		public void setMatrikelNr(int i) {
			matrikelNr = i;
		}

		/**
		 * @param string
		 */
		public void setNachname(String string) {
			nachname = string;
		}

		/**
		 * @param string
		 */
		public void setVorname(String string) {
			vorname = string;
		}

	}

	class Lecture {
		private String name;

		public Lecture(String n) {
			name = n;
		}

		/**
		 * @return
		 */
		public String getName() {
			return name;
		}

		/**
		 * @param string
		 */
		public void setName(String string) {
			name = string;
		}

	}
}
```

Na ja, nach dem was du schon gesagt hast scheinst du bisher alles richtig gemacht zu haben ... benutzt du zufällig eine "eigene " Hashmap Implementierung ?

Gruß Tom


----------



## Eva (4. Mai 2004)

Vom Aufbau her ist mein Beispiel mit deinem Codebeispiel fast gleich. 
Nur hab ich nicht die Elemente zuerst in den Vektor eingefügt, sondern zuerst in der HashMap einen leeren Vektor eingefügt, danach über den Key Person den entsprechenden Vektor geholt und dann erst Elemente eingefügt. 

Habe es jetzt zwar umgeändert, aber es war auch nicht der Fehler :-(
Schon langsam bin ich am verzweifeln.....

Eine Frage noch: hast du die Methode equals() vergessen oder bräuchte man die nicht implementieren 

eva


----------



## Eva (4. Mai 2004)

Außerdem: habe keine eigene hashMap implementiert, sondern die von java verwendet.


----------



## Thomas Darimont (4. Mai 2004)

Hallo!

Also ich hab die equals Methode bei diesem Beispiel weggelassen ...  es wird dann beim Vergleich einfach die equals Methode von Object angewandt welche auf Referenzgleichheit  prüft...

Wie sieht denn deine Hashfunktion aus ?
Gruß Tom


----------



## Eva (4. Mai 2004)

Eigentlich ähnlich deiner Implementierung. Ich habe aber nur die Matrikelnummer zur Berechnung verwendet, da diese eindeutig ist: 

public int hashCode() {
       if (hashCode == 0) 
          hashCode = (matrikel.hashCode() * 11);	
    return hashCode; 
}//hashCode

LG

Eva


----------



## Thomas Darimont (4. Mai 2004)

Hallo!

Hmmm... matrikelNr ist ein String, nicht wahr?

Dann laß doch das * 11 mal weg ... 

Gruß Tom


----------



## Eva (4. Mai 2004)

Nein, das ändert auch nichts  
Echt schlimm. 

Kannst du bitte mal folgendes Codestück bei deinem Beispiel einfügen (wenn es nicht zuviel Arbeit ist) 

Wenn ich nämlich diese Methode aufrufe, bekomme ich immer false, obwohl der Student in der HashMap vorhanden ist: 

  public boolean findStudent(Student s) {
   if (studentHM.containsKey(s)) {
      return true;
   }//if
   else 
      return false;
  }//findMatrikel

Danke, 

EVA


----------



## Thomas Darimont (4. Mai 2004)

Wieder Hallo!

Ich glaube so langsam wäre die ICQ Kommunikation effizienter ;-)


```
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/*
 * Created on 04.05.2004
 */

/**
 * @author Thomas Darimont
 */
public class HashtableTest {
	
	private HashMap map = new HashMap();

	public static void main(String[] args) {
		new HashtableTest().testIt();
	}

	/**
	 * 
	 */
	private void testIt() {

		

		Student tom = new Student("Darimont", "Thomas", 122342);

		List lectureList = new ArrayList();

		Lecture lecture0 = new Lecture("Programmierung");
		Lecture lecture1 = new Lecture("Analysis");
		Lecture lecture2 = new Lecture("Consulting");

		lectureList.add(lecture0);
		lectureList.add(lecture1);
		lectureList.add(lecture2);

		map.put(tom, lectureList);

		//..........
		
		System.out.println(findStudent(tom));

		List list = (List) map.get(tom);

		Object[] items = list.toArray();
		for (int i = 0; i < items.length; i++) {
			System.out.println(((Lecture) items[i]).getName());
		}

	}

	public boolean findStudent(Student s) {
		if (map.containsKey(s)) {
			return true;
		} //if
		else
			return false;
	} //findMatrikel

	class Student {
		private int hashCode;
		private String vorname;
		private String nachname;
		private int matrikelNr;

		public Student(String name, String vname, int matNr) {
			nachname = name;
			vorname = vname;
			matrikelNr = matNr;
		}

		public int hashCode() {
			if (hashCode == 0) {
				hashCode = (matrikelNr + vorname + nachname).hashCode();
			}
			return hashCode;
		}

		/**
		 * @return
		 */
		public int getMatrikelNr() {
			return matrikelNr;
		}

		/**
		 * @return
		 */
		public String getNachname() {
			return nachname;
		}

		/**
		 * @return
		 */
		public String getVorname() {
			return vorname;
		}

		/**
		 * @param i
		 */
		public void setMatrikelNr(int i) {
			matrikelNr = i;
		}

		/**
		 * @param string
		 */
		public void setNachname(String string) {
			nachname = string;
		}

		/**
		 * @param string
		 */
		public void setVorname(String string) {
			vorname = string;
		}

	}

	class Lecture {
		private String name;

		public Lecture(String n) {
			name = n;
		}

		/**
		 * @return
		 */
		public String getName() {
			return name;
		}

		/**
		 * @param string
		 */
		public void setName(String string) {
			name = string;
		}

	}
}
```

Ausgabe:



> true
> Programmierung
> Analysis
> Consulting



Gruß Tom


----------



## Eva (4. Mai 2004)

Ja stimmt, ICQ wäre effizienter...

Aber wie ich sehe, funktioniert bei dir das Teil Das gibts ja nicht....

Ich werde wahrscheinlich irgendeinen kleinen Fehler haben, aber bei mir gehts echt nicht...

eva


----------



## Snape (5. Mai 2004)

> _Original geschrieben von Eva _
> *Nein, das ändert auch nichts
> Echt schlimm.
> 
> ...



Hast Du eine equals()-Methode in der Student-Klasse? Wenn ja, wie sieht sie aus?


----------



## Snape (5. Mai 2004)

> _Original geschrieben von Eva _
> *Ich habe mal ein Objekt Person und Objekte von Lehrveranstaltung:
> 
> Person p0 = new Person("sem02010", "Eva" , "Langegger");
> ...



Hm, komischer aber korrekter Code... Was ist, wenn Du den Vector vorher erzeugst und erst dann den HashMap Eintrag vornimmst, wenn auch was im Vector drin steht? Also ungefähr so:

```
Vector myVector = new Vector();
myVector.add( I0 );
studentHashMap.put( p0, myVector );
```

Oder geht das nicht, weil Du nachträglich in dem Vector was eintragen/ändern musst? Dann solltest Du einmal darüber nachdenken:

```
studentHashMap.put(p0, new Vector());
Vector vec0 = (Vector) studentHashMap.get(p0); 
vec0.add(l0); 
studentHashMap.put(p0, vec0);
```
Musst nur mal schauen, ob bei gleichem Key der alte Eintrag überschrieben wird. Wenn nicht, den alten Eintrag per remove entfernen.


----------



## Eva (5. Mai 2004)

Hallo, 

danke für deine Hilfe, aber ich bin gestern in der Nacht noch auf meinem Fehler draufgekommen: 
Ich habe meine Methode equals() falsch überschrieben :-( 
naja, aber jetzt weiß ich wenigstens....

lg
eva


----------

