Zum Inhalt springen

Problem mit Hashtable


ostpower

Empfohlene Beiträge

Hallo zusammen,

ich möchte eine Hashtable benutzen, um Sonderzeichen zu codieren. Das sieht dann so ungefähr aus:


Hashtable h = new Hashtable();


h.put("!","!");

h.put(""",""");           //<-Problem

h.put("#","#");

h.put(".\",".\");   //<-Problem

Jetzt gibt es aber ein Problem mit dem Anführungszeichen ". Die Werte werden ja in "" geschrieben, wenn ich jetzt aber selber ein " dort reinschreiben will geht das nicht. Wie kann ich das lösen? Das Gleiche gilt für \ Das darf ich auch nicht eingeben.

vg

Bearbeitet von ostpower
Link zu diesem Kommentar
Auf anderen Seiten teilen

Du musst Sonderzeichen wie " oder \ maskieren. Zusätzlich solltest Du Deine Hashtable mit passenden Typen versehen. Hashtable ist eine generische Datenstruktur, da Du mit Strings arbeitest, solltest bei der Deklaration und dem Konstruktoraufruf auch die passenden Typen mitgeben

Wie meinst du das? Wo soll ich den Typ mitgeben? Kannst du ein Beispiel nennen/schreiben?

Link zu diesem Kommentar
Auf anderen Seiten teilen

Wie meinst du das? Wo soll ich den Typ mitgeben? Kannst du ein Beispiel nennen/schreiben?

Bei generischen Datentypen gibt man normalerweise den Datentyp mit an, der dort gespeichert werden soll.


Hashtable<String, String> h = new Hashtable<String, String>();

Bei deiner Deklaration lässt sich alles mögliche in die Map schreiben, z.B. auch eine Key-Schlüssel-Kombination aus Integers und irgendwelchen Objects.

Galileo Computing :: Java ist auch eine Insel (8. Auflage) – 9 Generics, innere Klassen

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ok, ich habe eine weitere Frage bzgl. der Schachtelung. Ich wollte mit zuerst mit einer for-schleife die einzelnen Zeichen durchlaufen und dann in einer weiteren schleife die hashtable durchlaufen, und dadurch das zeichen mit der hashtable abgleichen, aber das klappt nicht so recht:


for(int i=0; i<eingabe.length();i++){

	while(e.hasMoreElements()){

		Object hash = e.nextElement();

		Object zeichen = eingabe.charAt(i);


		if(zeichen == hash){

			System.out.println("treffer");

		}

		else{

			System.out.println("ok");

		}

		break;

	}

}

Wenn ich das so mache, dann nimmt er nur das erste zeichen, vergleicht es mit allen hash-werten gibt den status "ok" für jeden hashwert aus.

Bei der eingabe von "Ein < Test" möchte ich aber sowas kriegen:

ok

ok

ok

ok

treffer

ok

ok

ok

ok

ok

Wie mach ich das?

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich wollte mit zuerst mit einer for-schleife die einzelnen Zeichen durchlaufen und dann in einer weiteren schleife die hashtable durchlaufen
Man "durchläuft" keine Hashtabelle, das widerspricht dem ganzen Konzept. Man benutzt Hashtabellen ja gerade deshalb, weil man sich das Durchlaufen ersparen möchte. Wenn du sowieso nur sequenziell durch die Einträge hechelst, brauchst du keine Hashtabelle, da tut's auch eine unsortierte Liste.

Schau dir mal die Methode containsKey an.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Man "durchläuft" keine Hashtabelle, das widerspricht dem ganzen Konzept. Man benutzt Hashtabellen ja gerade deshalb, weil man sich das Durchlaufen ersparen möchte. Wenn du sowieso nur sequenziell durch die Einträge hechelst, brauchst du keine Hashtabelle, da tut's auch eine unsortierte Liste.

Schau dir mal die Methode containsKey an.

nee ich wills ja mit ner Hashtable machen. Aber wie mach ich das dann, dass er den String mit der Hashtable abgleicht?

Link zu diesem Kommentar
Auf anderen Seiten teilen

nee ich wills ja mit ner Hashtable machen. Aber wie mach ich das dann, dass er den String mit der Hashtable abgleicht?

Und jetzt liest du dir nochmal einmal GENAU durch was Klotzkopp dir dazu geschrieben hast, und schreist nicht einfach "nee".

Vor allem seinen letzten Satz solltest du dir mal zu Gemüte führen, weil das quasi schon deine Lösung ist.

Außerdem scheinst du dich mit den Generics auch noch nicht beschäftigt zu haben, oder benutzt du eine Java Version < 1.5?

Link zu diesem Kommentar
Auf anderen Seiten teilen

Man "durchläuft" keine Hashtabelle, das widerspricht dem ganzen Konzept. Man benutzt Hashtabellen ja gerade deshalb, weil man sich das Durchlaufen ersparen möchte. Wenn du sowieso nur sequenziell durch die Einträge hechelst, brauchst du keine Hashtabelle, da tut's auch eine unsortierte Liste.

Schau dir mal die Methode containsKey an.

ContainsKey würde eigentlich gut passen, nur erwartet er einen String, da die einzelnen Zeichen des Strings aber vom Typ char sind, geht das so nicht. Ein Cast von char zu String gehta auch nicht.


for(int i=0; i<eingabe.length();i++){

	if(h.containsKey(eingabe.charAt(i))){

         	System.out.println("Treffer" + eingabe.charAt(i));

	}

	else{

	        System.out.println("Kein Treffer");

	}

}

Link zu diesem Kommentar
Auf anderen Seiten teilen

ContainsKey würde eigentlich gut passen, nur erwartet er einen String, da die einzelnen Zeichen des Strings aber vom Typ char sind, geht das so nicht. Ein Cast von char zu String gehta auch nicht.


for(int i=0; i<eingabe.length();i++){

	if(h.containsKey(eingabe.charAt(i))){

         	System.out.println("Treffer" + eingabe.charAt(i));

	}

	else{

	        System.out.println("Kein Treffer");

	}

}

Hat sich erstmal erledigt. Es klappt jetzt.

Link zu diesem Kommentar
Auf anderen Seiten teilen

String (Java Platform SE 6)

Ansonsten wäre es nett für andere Leute die vielleicht ein ähnliches Problem haben, dein Lösung zu posten.

Ja ganz ruhisch, hätte ich noch gepostet, da ich mit gesamten Thema eh noch nicht fertig bin. Also es lag an den Typen der Hastable, wenn man ein Wert als Character angibt klappt es.


Hashtable<Character, String> h = new Hashtable<Character, String>();

Ich hab jetzt allerdings ein neues Problem. Ich habe nicht nur einzelne Zeichen in der Hashtable stehen sonder auch mehrere, z.B. "./"

Jetzt kann ich nicht mehr den eingabe-string zeichenweise durchlaufen, weil er ja dann . und / überprüft aber nicht ./

Ich müsste also den String nicht nach einem Zeichen sondern einer Zeichenkette durchsuchen. Es gibt zwar die String-Methode contains, aber das klappt nicht so recht.

Link zu diesem Kommentar
Auf anderen Seiten teilen


Hashtable<Character, String> h = new Hashtable<Character, String>();

Das bedeutet, dass Du genau einen Character als Hashschlüssel verwendest

Ich müsste also den String nicht nach einem Zeichen sondern einer Zeichenkette durchsuchen. Es gibt zwar die String-Methode contains, aber das klappt nicht so recht.

Doch, es ist genau das was die Definition einer Hashtabelle ist. Du hast einen Schlüssel und ordnest diesem Schlüssel einen Wert zu. Bei Dir ist der Schlüssel ein einzelner Character.

Ein Hashtabelle ist dafür gedacht um möglichst effizient abhängig von einem Wert ein Element wieder zu finden, ohne dass man aufwendig durchsuchen muss.

Also entweder benutzt Du mehrere Hashwerte, wobei ich dann zu Strings und nicht zu Charactern raten würde, in Du dann eben alle Deine Schlüssel einfügst oder Du musst Dir Gedanken über eine andere Datenstruktur machen

Link zu diesem Kommentar
Auf anderen Seiten teilen

Das bedeutet, dass Du genau einen Character als Hashschlüssel verwendest

Doch, es ist genau das was die Definition einer Hashtabelle ist. Du hast einen Schlüssel und ordnest diesem Schlüssel einen Wert zu. Bei Dir ist der Schlüssel ein einzelner Character.

Ein Hashtabelle ist dafür gedacht um möglichst effizient abhängig von einem Wert ein Element wieder zu finden, ohne dass man aufwendig durchsuchen muss.

Also entweder benutzt Du mehrere Hashwerte, wobei ich dann zu Strings und nicht zu Charactern raten würde, in Du dann eben alle Deine Schlüssel einfügst oder Du musst Dir Gedanken über eine andere Datenstruktur machen

Also die Dekleration meiner Hashtable lautet jetzt


Hashtable<String, String> h = new Hashtable<String, String>();

Denn ich habe auch als Key mehrere Zeichen wie z.B. "./"

Ich komme allerdings nicht darauf wie ich das abprüfen kann. Kann mir jemand mal ein Codebeispiel geben, wie ich einen Eingabe-String überprüfe, und dabei alle Zeichen bzw. Zeichenketten innerhalb des Eingabe-Strings, die in der Hashtable stehen, austausche?

Link zu diesem Kommentar
Auf anderen Seiten teilen

Denn ich habe auch als Key mehrere Zeichen wie z.B. "./"
Wie lang können die Keys denn werden? Passiert mit einem einzelnen Punkt oder Slash etwas anderes als mit dieser Kombination?

Du kannst jeden Substring der zu prüfenden Zeichenkette, eben bis zur maximalen Länge der Keys, gegen die Hashtable prüfen. Dazu brauchst du zwei verschachtelte Schleifen, eine für die Startposition und eine für die Länge des Substrings.

Wenn es viele Einzelzeichen-Keys und nur wenige Zeichenketten-Keys gibt, könntest du die Einzelzeichen mit einer Hashtable verarbeiten und die längeren mit einer Liste und Suchen&Ersetzen. Dabei musst du aber penibel darauf achten, dass nicht bereits ersetzte Zeichen nochmals verarbeitet werden.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich komme allerdings nicht darauf wie ich das abprüfen kann. Kann mir jemand mal ein Codebeispiel geben, wie ich einen Eingabe-String überprüfe, und dabei alle Zeichen bzw. Zeichenketten innerhalb des Eingabe-Strings, die in der Hashtable stehen, austausche?

Im Pseudocode


string newstring = ""

for(int i=0; i < mystring.length; ++i)

      if (hashtable.contains(mystring.charat(i))

           newstring += hashtable.getvalue(mystring.charat(i))

      else

           newstring += mystring.char.charat(i);

@Klotzkopp: Im Grunde geht das auch mit einer Hashtable, wobei man dann eben aus dem String, den man ersetzen will, eben via "substr" immer Zeichenketten ausschneidet und die auch als Keys in der Hashtable gespeichert sind.

Letztendlich würde ich mir aber da eher die Gedanken machen, wie viele Elemente in der Hashtabelle sein müssen und wie lang maximal die Substrings sein können, denn man hätte ja dann immer grob:

for (length of string)

for (max length of substring)

Wobei das grob abgeschätzt O(n^2) [sofern die Länge des Substrings = Länge des Strings wird] + die Suche in der Hashtabelle ist. Das wäre sicherlich nicht sehr effizient. Ich denke auch der Vorschlag mit einer iterativen Nachbearbeitung wird knapp unterhalb von O(n^2) liegen.

Wenn es um sehr viele Ersetzungen geht würde ich über eine String-Alignment Algorithmen das machen (Sequenzalignment ? Wikipedia), um heraus zu bekommen, was überhaupt ersetzt werden muss und dann würden sich wohl http://de.wikipedia.org/wiki/String-Matching-Algorithmen anbieten

Link zu diesem Kommentar
Auf anderen Seiten teilen

Also die Hashtable hat 10 Einträge:


h.put("!" , "!");

h.put("\"",""");

h.put("#","#");

h.put("$","$");

h.put("%","%");

h.put("*","*");

h.put("+","+");

h.put("--","--");

h.put("./","./");

h.put("\\R","\R");	

Drei von den Werten bestehen also aus mehr als einem Zeichen. Was wäre da jetzt die effektivste Lösung? Mit charAt kann ich ja nicht arbeiten, da bei dem String "Ein -- Test" nur das "-" geprüft werden würde, nicht aber "--"

Link zu diesem Kommentar
Auf anderen Seiten teilen

Drei von den Werten bestehen also aus mehr als einem Zeichen. Was wäre da jetzt die effektivste Lösung? Mit charAt kann ich ja nicht arbeiten, da bei dem String "Ein -- Test" nur das "-" geprüft werden würde, nicht aber "--"

Du musst jedes Zeichen und eben immer zwei Zeichen prüfen, wie schon gesagt die Stringklasse von Java bietet substring an. Am sinnvollsten prüfst Du erst die längsten String und dann immer zum kürzesten.

Pseudocode


for(i=0; i < mystr.length-1; ++i)

     if hashmap.contains(mystr.substr(i,i+1))

          newstr += hashmap.getvalue(mystr.substr(i,i+1))

     else

          if hashmap.contains(mystr.charat(i))

               newstr += hashmap.getvalue(mystr.charat(i))

          else

               newstr += mystr.charat(i)


if hashmap.contains(mystr.charat(mystr.length-1))

        newstr += hashmap.getvalue(mystr.charat(mystr.length-1))

else

        newstr += mystr.charat(mystr.length-1)


Link zu diesem Kommentar
Auf anderen Seiten teilen

Also die Hashtable hat 10 Einträge:

[...]

Drei von den Werten bestehen also aus mehr als einem Zeichen. Was wäre da jetzt die effektivste Lösung? Mit charAt kann ich ja nicht arbeiten, da bei dem String "Ein -- Test" nur das "-" geprüft werden würde, nicht aber "--"

Ohne wirklich dein Problem, bzw. Lösung zu verstehen, schau mal hier:

Pattern (Java 2 Platform SE v1.4.2)

Link zu diesem Kommentar
Auf anderen Seiten teilen

@ostpower

noch ein Tip:

Bevor man eine Hashtable nach keys durchsucht sollte man sich überlegen ob es bessere Ansätze gibt.

Wenn es bei dir um suchen/ersetzen innerhalb eines Strings gehen sollte, wirst du dich mit regulären Ausdrücke beschäftigen müssen, sofern du eine effektive und effiziente Lösung anstrebst.

Beim Zusammensetzen von (vielen) Strings kann man auch StringBuilder oder die "threadsafe version" StringBuffer verwenden.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Dein Kommentar

Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung wiederherstellen

  Nur 75 Emojis sind erlaubt.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

Fachinformatiker.de, 2024 by SE Internet Services

fidelogo_small.png

Schicke uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App

Download on the App Store
Get it on Google Play

Kontakt

Hier werben?
Oder sende eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...