Die Klasse "StringBuffer"

<-- zurck zur Startseite | <- eine Seite vor | eine Seite weiter ->

  1. Anlegen eines StringBuffers
  2. L�ge und Puffergr�e abfragen
  3. Methoden zum Bearbeiten des StringBuffers
  4. �ung
  5. L�ung

1. Anlegen eines StringBuffers

StringBuffer bedeutet in etwa "Zeichenpuffer". Das Problem bei Strings wurde schon kurz angerissen: sie sind eigentlich unver�derlich ("immutable"). Aus dem Grund wird bei jeder Ver�derung des Strings, etwa beim Verketten oder Ersetzen, intern ein neues String-Objekt angelegt. Das ist freilich fr den Anwender und zun�hst auch fr den Programmierer nicht sichtbar. Bei nur kleinen und wenigen Ver�derungen, wie wir es bisher hatten, f�lt das auch kaum ins Gewicht, werden aber (z.B. innerhalb einer Schleife) in krzester Zeit extrem viele �derungsoperationen am String durchgefhrt, dann l�ft der Freispeicher ("Heap") nach und nach ber, durch die jeweils entstandenen Kopien.
Ein "StringBuffer" dagegen erlaubt es, wirklich ver�derliche Strings anzulegen. Dazu wird jeweils ein Standardpuffer angelegt, der um 16 Zeichen gr�er ist als der enthaltene String. Ver�dert der String seine L�ge, wird der Puffer automatisch erweitert, ohne dass eine Kopie vom Original-String gezogen werden muss. Ein StringBuffer sollte ergo immer dann eingesetzt werden, wenn viele Operationen zum Einfgen, Anh�gen und L�chen notwendig sind. Da die Klasse StringBuffer (etwas) weniger Methoden bereitstellt als die Klasse String, wird sie leider oft bergangen. Die Klasse StringBuffer ist ebenfalls im Paket java.lang zu finden.

Ein StringBuffer kann nicht wie ein String ber ein Literal erzeugt werden, sondern ben�igt den Aufruf des Konstruktors mittels des Schlsselwortes new:

StringBuffer sb1 = new StringBuffer();
StringBuffer sb2 = new StringBuffer(32);
StringBuffer sb3 = new StringBuffer("hier kommt ein Text");

Der erste Aufruf konstruiert einen leeren StringBuffer, der aber bereits einen Puffer fr 16 Zeichen bereitstellt (wird bei Ver�derungen automatisch erweitert). Die zweite Variante des Konstruktors erh�t eine Ganzzahl als �ergabeparameter: damit wird die Gr�e des Puffers explizit festgelegt (hier: 32 Zeichen). Der dritte Konstruktor legt aus dem bergebenen String ein StringBuffer-Objekt an und stellt gleichzeitig wieder einen Standardpuffer fr 16 weitere Zeichen bereit.

nach oben

2. L�ge und Puffergr�e abfragen

Zur Bestimmung der L�ge des StringBuffers gibt es mehrere Methoden:

public int length()
public int capacity()

W�rend die Methode length schon hinreichend bekannt sein drfte, ist die Methode capacity neu: sie gibt die L�ge des gesamten, belegten Speicherplatzes zurck, also L�ge + Puffer. Bedeutend ist fr uns erstmal aber nur die Methode "length", da der StringBuffer ohnehin immer automatisch erweitert wird, so dass die Bestimmung des Puffers mehr der Optimierung des Programms fr Profis dient.
Bei einem StringBuffer lassen sich auch die L�ge des Strings und der Minimumpuffer manuell einstellen. Dazu dienen die Methoden setLength und ensureCapacity. Fr uns sind sie aber vorerst uninteressant, insofern sei Interessierten ein Blick in die Java-Doku nahegelegt.
Ein kleines Beispiel:

StringBuffer sb1 = new StringBuffer(32);
StringBuffer sb2 = new StringBuffer("hallo");
System.out.println(sb1.length());
System.out.println(sb1.capacity());
System.out.println(sb2.length());
System.out.println(sb2.capacity());

Der erste erzeugte StringBuffer ist leer, deshalb ist seine L�ge auch 0. Die Gr�e des belegten Speichers betr�t hingegen 32 (L�ge + Puffer = 0 + 32 = 32). Der zweite StringBuffer beinhaltet die Zeichenkette "hallo". Seine L�ge betr�t daher 5, der belegte Speicher 21 (5 + 16 = 21), da hier ein Standardpuffer von 16 Zeichen angelegt wurde.

nach oben

3. Methoden zum Bearbeiten des StringBuffers

Folgende Methoden sind dazu angedacht, den StringBuffer zu bearbeiten:

public StringBuffer append(String str)
public StringBuffer insert(int offset, String str)
public StringBuffer delete(int start, int end)
public StringBuffer deleteCharAt(int index)
public void setCharAt(int index, char ch)
public StringBuffer replace(int start, int end, String str)
public StringBuffer reverse()
public String substring(int start)
public String substring(int start, int end)
public char charAt(int index)
public String toString()

Die Methode append h�gt den bergebenen String an den aktuellen StringBuffer, zu dem diese Methode aufgerufen wurde, an. Sie entspricht damit einer String-Verkettung.
Die Methode insert fgt den als zweites Argument bergebenen String an die Position ein, die als erstes Argument bergeben wurde. Der Index erstreckt sich - wie blich - von 0 bis length()-1. Ausserdem k�nen diesen beiden Methoden nicht nur Strings, sondern auch primitive Datentypen, Objekte oder ein Array aus "char" bergeben werden.
Die Methode delete entfernt eine Zeichenkette aus dem StringBuffer-Objekt. �ergeben werden Anfangs- und Endposition des zu l�chenden Teilstrings. Der End-Index gibt die Position des Zeichens an, das gerade nicht mehr gel�cht werden soll!
Die Methode deleteCharAt l�cht demgegenber nur ein einziges Zeichen, das an dem als Argument bergeben Index liegt.
Bei der Methode setCharAt wird ein einzelnes Zeichen an einer bestimmten Position (erstes Argument) durch ein anderes Zeichen ersetzt, das als zweites Argument bergeben wird. Die Indexgrenzen des StringBuffers drfen nicht berschritten werden, ansonsten wird wieder eine StringIndexOutOfBoundsException ausgel�t. Diese Methode besitzt keinen Rckgabewert, die Ver�derung wird am aktuellen StringBuffer durchgefhrt.
Die Verwendung der Methode replace unterscheidet sich von derjenigen der Klasse "String". Im aktuellen StrungBuffer wird der Teilstring zwischen der Start- und Endposition (erstes und zweites Argument) durch einen anderen String (drittes Argument) ersetzt. Mit dieser Methode kann man nicht nur einzelne Zeichen ersetzen, sondern auch ganze Teilstrings. Freilich kann sich dabei auch die L�ge des StringBuffers �dern. Diese Methode steht ab dem JDK1.2 zur Verfgung und ist damit in vielen Applets leider nicht verwendbar, da derzeit noch viele Browser keine Java2-Laufzeitumgebung ohne Plug-In zur Verfgung stellen.
Die Methode reverse dreht einen StringBuffer von hinten nach vorne um.
Die Verwendung der Methode substring gleicht der der gleichnamigen Methode aus der Klasse "String", so dass hier nicht n�er darauf eingegangen wird. Interessant ist aber, dass diese Methode keinen StringBuffer, sondern einen normalen String zurckliefert.
Ausserdem beinhaltet die Klasse "StringBuffer" auch eine Methode charAt, mit der das Zeichen an der bergebenen Position zurckgegeben wird. Der Rckgabewert ist vom Typ "char".
Extrem wichtig ist die Methode toString, die den StringBuffer zurck in einen String wandelt.

StringBuffer sb = new StringBuffer("Hallo");
sb = sb.append(", wie geht es dir?");
sb = sb.insert(6, " Christof");
System.out.println(sb.toString());
sb = sb.delete(0, 7);
System.out.println(sb.toString());
sb = sb.replace(7, 8, "ph");
System.out.println(sb.toString());
System.out.println(sb.reverse().toString());

Dieses Beispiel zeigt nur mehr ein paar der Methoden, da die restliche Methoden bereits mit den bisher erworbenen Kenntnissen angewendet werden k�nen. Hier sei auch wieder zum eigenst�digen Herumprobieren angeregt!
Zuerst wird der soeben angelegte StringBuffer mit der Methode "append" erweitert zu dem Satz "Hallo, wie geht es dir?". Anschlie�nd wird mit der Methode "insert" an die Position 6 (hier steht bis jetzt das Komma hinter "hallo") eingefgt, der Rest verschiebt sich entsprechend nach hinten. Bei der Ausgabe auf dem Bildschirm wird der StringBuffer mit der Methode "toString" zurck in einen normalen String verwandelt. Der Satz lautet nun "Hallo Christof, wie geht es dir?".
Jetzt wird mit der Methode "delete" das "Hallo" gel�cht. Die Position 7 zeigt dabei auf das "C" von "Christof" und ist ergo das erste Element, das nicht mehr gel�cht werden soll. Da ich aber Christoph und nicht Christof hei�, �dern wir das auch noch, und zwar mittels der Methode "replace": die Startposition 7 zeigt beim jetzt verkrzten String genau auf das "f", die Endposition 8 befindet sich genau dahinter, da wir ja nur das "f" austauschen wollen, und zwar durch "ph".
Bei der letzten Ausgabe sieht man einen Trick: hier wurden mehrere Methodenaufrufe aneinandergeh�gt! Das ist durchaus legitim, und der Compiler geht dabei wie folgt vor: er liest zun�hst den Ausdruck von Links nach rechts und fhrt zun�hst die Methode "reverse", die den StringBuffer umdreht, aus: das Ergebnis dieser Operation ist erneut ein StringBuffer, so dass auf diesem dann im zweiten Schritt auch die Methode "toString" ausgefhrt werden kann. Dieses Verfahren sieht man �ter, da ja Programmierer Tippfaul sind. Es ist natrlich auch nicht auf StringBuffer begrenzt! Man kann sich das Vorgehen so vorstellen:

sb.reverse().toString() --> Methode reverse -- > sb.toString() --> Methode toString --> String

Seit dem JDK1.4 wurde die Klasse "StringBuffer" nochmal um einige Methoden erweitert, n�lich um die Methoden indexOf und lastIndexOf zum Auffinden von Teilstrings im StringBuffer. Diese Methoden arbeiten analog zu den gleichnamigen String-Methoden.

nach oben

4. �ung

In der Skriptsprache PHP existiert eine Funktion namens "htmlspecialchars". Sie dient dazu, einen HTML-Text so aufzubereiten, dass er vom Browser nicht als HTML-Text interpretiert wird, sondern als Quelltext angezeigt werden kann. Dabei werden lediglich folgende Zeichen im Text ersetzt (sog. "Entities"):
< wird zu &lt;
> wird zu &gt;
& wird zu &amp;
" wird zu &quot;

Schreibe eine Methode "htmlSpecialChars" in Java, die diese Arbeit erledigt. Sie soll als Argument einen String (den HTML-Text) erhalten und ebenso einen String zurckliefern.

nach oben

5. L�ung

public class ConvertHTML {

  public static String htmlSpecialChars(String htmltext) {
    StringBuffer sb = new StringBuffer();
    for (int i=0; i<htmltext.length(); i++) {
      char elem = htmltext.charAt(i);
      if (elem == '<')
          sb.append("&lt;");
      else if (elem == '>')
          sb.append("&gt;");
      else if (elem == '&')
          sb.append("&amp;");
      else if (elem == '"')
          sb.append("&quot;");
      else
          sb.append(elem);
    }
    return sb.toString();
  }
  
  public static void main(String[] args) {
    String htmltext = "<html><body><h1>Servus & Gute Nacht</h1></body></html>";
    htmltext = htmlSpecialChars(htmltext);
    System.out.println(htmltext);
  }
  
}

Diese Aufgabe ist recht knifflig. Das Problem ist, dass wir in Java keine einfache Methode haben, einen Teilstring einfach durch einen anderen zu ersetzen (lediglich Einzelzeichen sind m�lich). Die L�ung besteht nun darin, den Text Zeichen fr Zeichen zu durchlaufen und jeweils zu prfen, ob es sich um eines der Zeichen handelt, die umgewandelt werden mssen.
Zuerst wir ein leerer StringBuffer angelegt und eine for-schleife initialisiert, die vom Index 0 bis zum Ende des bergebenen Textes l�ft. An jeder Stelle wird mittels der Methode "charAt" das jeweilige Zeichen als "char" zurckgeliefert. Dann wird anhand einiger if- und else if-Bl�ke berprft, ob es sich um eines der Zeichen <, >, & oder " handelt. Ist dies der Fall, wird an den StringBuffer das entsprechende Entity angeh�gt. Bei allen anderen Zeichen wird der else-Block angesteuert und das Zeichen ohne Modifikation an den StringBuffer angefgt. Beim Verlassen der Methode wird der StringBuffer noch zu einen einfachen String konvertiert. Anstelle der vielen else if-Bl�ke w�e natrlich auch eine switch-Anweisung m�lich gewesen.
Diese Methode macht in einer Applikation freilich wenig Sinn, aber sie ist interessant, wenn man sich sp�er mit Servlets oder JSP besch�tigen will. So k�nen z.B. G�tebucheintr�e "ges�bert" werden. Darber hinaus zeigt diese Methode beispielhaft den sinnvollen Einsatz eines StringBuffers. H�te man hier mit normalen Strings gearbeitet, so h�te sich bei l�geren Text massig Datenmll durch die vielen Kopien des String-Objekts angesammelt.

nach oben