Galileo Computing < openbook > Galileo Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger.

Inhaltsverzeichnis
Vorwort
1 Java ist auch eine Sprache
2 Sprachbeschreibung
3 Klassen und Objekte
4 Der Umgang mit Zeichenketten
5 Mathematisches
6 Eigene Klassen schreiben
7 Angewandte Objektorientierung
8 Exceptions
9 Die Funktionsbibliothek
10 Threads und nebenläufige Programmierung
11 Raum und Zeit
12 Datenstrukturen und Algorithmen
13 Dateien und Datenströme
14 Die eXtensible Markup Language (XML)
15 Grafische Oberflächen mit Swing
16 Grafikprogrammierung
17 Netzwerkprogrammierung
18 Verteilte Programmierung mit RMI und Web-Services
19 JavaServer Pages und Servlets
20 Applets
21 Midlets und die Java ME
22 Datenbankmanagement mit JDBC
23 Reflection und Annotationen
24 Logging und Monitoring
25 Sicherheitskonzepte
26 Java Native Interface (JNI)
27 Dienstprogramme für die Java-Umgebung
A Die Begleit-DVD
Stichwort

Download:
- ZIP, ca. 12,5 MB
Buch bestellen
Ihre Meinung?

Spacer
<< zurück
Java ist auch eine Insel von Christian Ullenboom
Programmieren mit der Java Standard Edition Version 6
Buch: Java ist auch eine Insel

Java ist auch eine Insel
7., aktualisierte Auflage
geb., mit DVD (November 2007)
1.492 S., 49,90 Euro
Galileo Computing
ISBN 978-3-8362-1146-8
Pfeil 4 Der Umgang mit Zeichenketten
Pfeil 4.1 Einzelne Zeichen mit der Character-Klasse behandeln
Pfeil 4.2 Strings und deren Anwendung
Pfeil 4.2.1 String-Literale als String-Objekte für konstante Zeichenketten
Pfeil 4.2.2 String-Länge und Test auf Leerstring
Pfeil 4.2.3 Nach enthaltenen Zeichen und Zeichenfolgen suchen
Pfeil 4.2.4 Gut, dass wir verglichen haben
Pfeil 4.2.5 String-Teile extrahieren
Pfeil 4.2.6 Strings anhängen, Groß-/Kleinschreibung und Leerraum
Pfeil 4.2.7 Suchen und ersetzen
Pfeil 4.2.8 String-Objekte mit Konstruktoren neu anlegen
Pfeil 4.3 Konvertieren zwischen Primitiven und Strings
Pfeil 4.3.1 Unterschiedliche Typen in Zeichenketten konvertieren
Pfeil 4.3.2 String in primitives Element konvertieren
Pfeil 4.4 Veränderbare Zeichenketten mit StringBuffer/StringBuilder
Pfeil 4.4.1 Anlegen von StringBuffer/StringBuilder-Objekten
Pfeil 4.4.2 Die Länge eines StringBuffer/-Builder-Objekts
Pfeil 4.4.3 Daten anhängen
Pfeil 4.4.4 Zeichen(folgen) setzen, erfragen, löschen und umdrehen
Pfeil 4.4.5 Vergleichen von String/StringBuffer/StringBuilder
Pfeil 4.4.6 hashCode() bei StringBuffer/StringBuilder
Pfeil 4.5 Sprachabhängiges Vergleichen und Normalisierung
Pfeil 4.5.1 Die Klasse Collator
Pfeil 4.5.2 Effiziente interne Speicherung für die Sortierung
Pfeil 4.5.3 Normalisierung
Pfeil 4.6 Reguläre Ausdrücke
Pfeil 4.6.1 Die Klassen Pattern und Matcher
Pfeil 4.6.2 Mit MatchResult alle Ergebnisse einsammeln
Pfeil 4.7 Zerlegen von Zeichenketten
Pfeil 4.7.1 Splitten von Zeichenketten mit split()
Pfeil 4.7.2 split() in Pattern
Pfeil 4.7.3 Die Klasse Scanner
Pfeil 4.7.4 StringTokenizer
Pfeil 4.7.5 BreakIterator als Zeichen-, Wort-, Zeilen- und Satztrenner
Pfeil 4.8 Zeichenkodierungen und Base64
Pfeil 4.8.1 Über die Klasse String Kodierungen vornehmen
Pfeil 4.8.2 Konvertieren mit OutputStreamWriter-Klassen
Pfeil 4.8.3 Das Paket java.nio.charset
Pfeil 4.8.4 Base64-Kodierung
Pfeil 4.9 Formatieren von Ausgaben
Pfeil 4.9.1 Formatieren mit format() aus String
Pfeil 4.9.2 Die Format-Klassen im Überblick
Pfeil 4.9.3 Zahlen, Prozente und Währungen mit NumberFormat und DecimalFormat formatieren
Pfeil 4.9.4 Ausgaben mit MessageFormat formatieren
Pfeil 4.10 Zum Weiterlesen


Galileo Computing - Zum Seitenanfang

4.4 Veränderbare Zeichenketten mit StringBuffer/StringBuilder Zur nächsten ÜberschriftZur vorigen Überschrift

Zeichenketten, die in der virtuellen Maschine in String-Objekten gespeichert sind, haben die Eigenschaft, dass ihr Inhalt nicht mehr verändert werden kann. Anders verhalten sich die Exemplare der Klasse StringBuffer und StringBuilder, an denen sich Veränderungen vornehmen lassen. Die Veränderungen betreffen anschließend das StringBuffer/StringBuilder-Objekt selbst, und es wird kein neu erzeugtes Objekt als Ergebnis geliefert, wie zum Beispiel beim Plus-Operator und der concat()-Methode bei herkömmlichen String-Objekten. Sonst sind sich aber die Implementierung von String-Objekten und StringBuffer/StringBuffer-Objekten ähnlich. In beiden Fällen nutzen die Klassen ein internes Zeichenfeld.

Die Klasse StringBuilder bietet die gleichen Funktionen wie StringBuffer, nur nicht synchronisiert. Bei nebenläufigen Programmen kann daher die interne Datenstruktur vom StringBuilder-Objekt inkonsistent werden, ist aber dafür bei nicht-nebenläufigen Zugriffen ein wenig schneller.


Galileo Computing - Zum Seitenanfang

4.4.1 Anlegen von StringBuffer/StringBuilder-Objekten Zur nächsten ÜberschriftZur vorigen Überschrift

Mit mehreren Konstruktoren lassen sich StringBuffer/StringBuilder-Objekte generieren.


final class java.lang.StringBuffer 
final class java.lang.StringBuilder 
implements Appendable, CharSequence, Serializable

  • StringBuffer(), StringBuilder() Legt ein neues Objekt an, das die leere Zeichenreihe enthält und Platz für (zunächst) bis zu 16 Zeichen bietet. Bei Bedarf wird automatisch Platz für weitere Zeichen bereitgestellt.
  • StringBuffer( int length ), StringBuilder( int length ) Wie oben, jedoch reicht die anfängliche Kapazität des Objekts für die angegebene Anzahl an Zeichen. Optimalerweise ist die Größe so zu setzen, dass sie der Endgröße der dynamischen Zeichenfolge nahe kommt.
  • StringBuffer( String str ), StringBuilder( String str ) Baut ein Objekt, das eine Kopie der Zeichen aus str enthält. Zusätzlich wird bereits Platz für 16 weitere Zeichen eingeplant.
  • StringBuffer( CharSequence seq ), StringBuilder( CharSequence seq ) Erzeugt ein neues Objekt aus einer CharSequence. Damit können auch die Zeichenfolgen anderer StringBuffer und StringBuilder-Objekte Basis dieses Objekts werden.

Da nur String-Objekte von der Sprache bevorzugt werden, bleibt uns allein der explizite Aufruf eines Konstruktors, um StringBuffer/StringBuilder-Exemplare anzulegen. Alle String-Literale in Anführungszeichen sind ja schon Exemplare der Klasse String.


Hinweis Hinweis Weder in der Klasse String noch in StringBuffer/StringBuilder existiert ein Konstruktor, der explizit ein char als Parameter zulässt, um aus dem angegebenen Zeichen eine Zeichenkette aufzubauen. Dennoch gibt es bei StringBuffer/StringBuilder einen Konstruktor, der ein int annimmt, wobei die übergebene Ganzzahl die interne Startgröße des Puffers spezifiziert. Rufen wir den Konstruktor mit char auf – etwa einem »*« –, so konvertiert der Compiler automatisch das Zeichen in ein int. Das resultierende Objekt enthält kein Zeichen, sondern hat nur eine anfängliche Kapazität von 42 Zeichen, da 42 der ASCII-Code des Sternchens ist. Korrekt ist daher für ein Zeichen nur Folgendes: c new StringBuffer("" + c) oder new StringBuffer().append(c).



Galileo Computing - Zum Seitenanfang

4.4.2 Die Länge eines StringBuffer/-Builder-Objekts Zur nächsten ÜberschriftZur vorigen Überschrift

Wie bei einem String lässt sich die Länge und die Anzahl der enthaltenen Zeichen mit der Methode length() erfragen. StringBuffer/StringBuilder-Objekte haben jedoch auch eine interne Puffergröße, die sich mit capacity() erfragen lässt und im Konstruktor wie beschrieben festgelegt wird. In diesem Puffer, der genauer gesagt ein Array vom Typ char ist, werden die Veränderungen wie das Ausschneiden oder Anhängen von Zeichen vorgenommen. Während length() die Anzahl der Zeichen angibt, ist capacity() immer größer oder gleich length() und sagt etwas darüber aus, wie viele Zeichen der Puffer noch aufnehmen kann, ohne dass intern ein neues, größeres Feld benötigt würde.


Beispiel Beispiel Es ergibt sb.length() 14, aber sb.capacity() ergibt 14 + 16 = 30.

StringBuffer sb = new StringBuffer( "www.tutego.com" ); 
int length   = sb.length();                           //  4 
int capacity = sb.capacity();                         // 20

Die Startgröße sollte mit der erwarteten Größe initialisiert werden, um späteres teures internes Vergrößern zu vermeiden. Falls der StringBuffer/StringBuilder einen großen internen Puffer hat, aber auf lange Sicht nur wenig Zeichen besitzt, lässt er sich mit trimToSize() auf eine kleinere Größe schrumpfen.

Ändern der Länge

Soll der StringBuffer/StringBuilder mehr Daten aufnehmen, so ändert setLength() die Länge auf eine angegebene Anzahl von Zeichen. Der Parameter ist die neue Länge. Ist sie kleiner als length(), so wird der Rest der Zeichenkette einfach abgeschnitten. Die Größe des internen Puffers ändert sich dadurch nicht. Ist setLength() größer, so vergrößert sich der Puffer, und die Methode füllt die übrigen Zeichen mit Nullzeichen '\0000' auf. Die Methode ensureCapacity() fordert, dass der interne Puffer für eine bestimmte Anzahl von Zeichen ausreicht. Wenn nötig, legt sie ein neues, vergrößertes char-Array an, verändert aber nicht die Zeichenfolge, die durch das StringBuffer-Objekt repräsentiert wird.


Galileo Computing - Zum Seitenanfang

4.4.3 Daten anhängen Zur nächsten ÜberschriftZur vorigen Überschrift

Die häufigste Anwendung von StringBuffer/StringBuilder-Objekten ist das Zusammenfügen von Texten aus Daten unterschiedlichen Typs. Dazu deklarieren StringBuffer bzw. StringBuilder eine Reihe von append()-Methoden, die mit unterschiedlichen Datentypen überladen sind. Die append()-Methoden von StringBuilder geben einen StringBuilder zurück und die von StringBuffer einen StringBuffer.

  • StringBuffer/StringBuilder append( boolean b )
  • StringBuffer/StringBuilder append( char c )
  • StringBuffer/StringBuilder append( char[] str )
  • StringBuffer/StringBuilder append( char[] str, int offset, int len )
  • StringBuffer/StringBuilder append( CharSequence s )
  • StringBuffer/StringBuilder append( CharSequence s, int start, int end )
  • StringBuffer/StringBuilder append( double d )
  • StringBuffer/StringBuilder append( float f )
  • StringBuffer/StringBuilder append( int i )
  • StringBuffer/StringBuilder append( long lng )
  • StringBuffer/StringBuilder append( Object obj )
  • StringBuffer/StringBuilder append( String str )
  • StringBuffer/StringBuilder append( StringBuffer sb )

Drei der Methoden – mit den Argumenten (char), (CharSequence), (CharSequence, int, int) – werden von der Schnittstelle Appendable vorgeschrieben.

Besonders nützlich ist in der Praxis append(CharSequence, int, int), da sich auf diese Weise Teile von String-, StringBuffer- und StringBuilder-Objekten anhängen lassen. Die append()-Methoden hängen immer an das Ende an und vergrößern den internen Platz – das interne char-Feld –, falls es nötig ist. Ein neues StringBuffer/StringBuilder-Objekt wird nicht erzeugt.


Beispiel Beispiel Jede append()-Methode verändert den StringBuffer/StringBuilder und liefert als Rückgabewert noch eine Referenz darauf zurück. Das hat den großen Vorteil, dass sich Aufrufe der append()-Methoden einfach hintereinander setzen (kaskadieren) lassen:

StringBuffer sb = new StringBuffer( "George Peppard " ).append(','); 
sb.append(" Mr. T, ").append("Dirk Benedict, ").append("Dwight Schultz");

Die Auswertung erfolgt von links nach rechts, so dass die Ausgabe ist: »George Peppard, Mr. T, Dirk Benedict, Dwight Schultz«.



Galileo Computing - Zum Seitenanfang

4.4.4 Zeichen(folgen) setzen, erfragen, löschen und umdrehen Zur nächsten ÜberschriftZur vorigen Überschrift

Die bekannten Anfrage-Methoden aus String finden wir auch beim StringBuffer/StringBuilder wieder. So verhalten sich charAt() und getChars() bei Exemplaren beider Klassen identisch. Auch substring(int start) und substring(int start, int end) sind aus der Klasse String bekannt.

Neu ist setCharAt(), da in einem StringBuffer/StringBuilder Zeichen verändert werden können.


Beispiel Beispiel Ändere das erste Zeichen im StringBuffer in einen Großbuchstaben:

StringBuffer sb = new StringBuffer( "spare Wasser und dusche mit der Freundin" ); 
char upperCharacter = Character.toUpperCase( sb.charAt(0) ); 
sb.setCharAt( 0, upperCharacter );

Das erste Argument 0 in setCharAt() steht für die Position des zu setzenden Zeichens.


Eine Folge von Zeichen lässt sich durch delete(int start, int end) löschen. deleteCharAt(int index) löscht nur ein Zeichen. In beiden Fällen wird ein inkorrekter Index durch eine StringIndexOutOfBoundsException bestraft. Die Methode replace(int start, int end, String str) löscht zuerst die Zeichen zwischen start und end und fügt anschließend den neuen String str ab start ein. Dabei sind die Endpositionen wie immer exklusiv, das heißt, sie geben das erste Zeichen hinter dem zu verändernden Ausschnitt an. Die Methode insert(int offset, Typ) fügt die Zeichenketten-Repräsentation eines Werts vom Typ Typ an die Stelle offset ein. Sie ähnelt der überladenen append()-Methode. Für char-Arrays existiert insert() in einer abgewandelten Art: insert(int index, char[] str, int offset, int len). Es wird nicht das komplette Array in den StringBuffer/StringBuilder übernommen, sondern nur ein Ausschnitt.


Beispiel Beispiel Setze das Zeichen »-« in ein StringBuilder-Objekt an die Position 3.

StringBuilder sb = new StringBuilder( "SubEtha-Sens-O-Matic" ); 
char val = '-'; 
sb.insert( 3, val );                       // Sub-Etha-Sens-O-Matic

Eine weitere Methode reverse() dreht die Zeichenfolge um.


Beispiel Beispiel Teste unabhängig von der Groß-/Kleinschreibung, ob der String s ein Palindrom ist. Palindrome lesen sich von vorne genauso wie von hinten, etwa »Rentner«.

boolean isPalindrome = new StringBuilder( s ).reverse().toString(). 
equalsIgnoreCase(s);


Galileo Computing - Zum Seitenanfang

4.4.5 Vergleichen von String/StringBuffer/StringBuilder Zur nächsten ÜberschriftZur vorigen Überschrift

Zum Vergleichen von Zeichenketten bietet sich naheliegenderweise die bekannte equals()-Methode an. Die ist aber bei StringBuffer/StringBuilder nicht wie erwartet implementiert. Dazu gesellen sich andere Methoden, die zum Beispiel unabhängig von der Groß-/Kleinschreibung vergleichen.

equals() bei der String-Klasse

Ein Blick in die API-Dokumentation der Klasse String zeigt eine equals()-Methode, mit der Zeichenketten vom Typ String verglichen werden können. equals() aus String überschreibt die Methode equals() aus Object, sodass der Parametertyp auch Object ist.

Die equals() Methode aus String vergleicht nur String/String-Paare, denn equals() beginnt erst dann den Vergleich, wenn das Argument auch vom Typ String ist. Das testet die Klasse mit einem speziellen Operator instanceof. Das bedeutet, einen String mit einem StringBuffer bzw. StringBuilder zu vergleichen, führt bei equals() zu keinem Compilerfehler (da equals(Object) alles entgegennimmt), aber auch zu nichts Sinnvollem, da der Vergleich immer false ist, auch wenn der StringBuffer-Objekt inhaltsgleich ist – ein StringBuffer ist kein String. String kann also nicht erfolgreich String/StringBuffer-Paare testen, und bei Objekten, die nicht vom Typ String sind, ruft equals() nicht automatisch etwas Magisches wie die Methode toString() auf den Objekten auf.

Eine Möglichkeit des Vergleichs ist daher, mit toString() den StringBuffer in ein String zu überführen und dann die beiden Strings mit equals() zu vergleichen.

contentEquals() beim String

Um einen String mit einem StringBuffer- oder StringBuilder-Objekt vergleichen zu können, nutzen wir statt der Methode equals() der Klasse String die Methode contentEquals(CharSequence). Die Methode liefert die Rückgabe true, wenn die CharSequence und der betrachtende String den gleichen Zeicheninhalt haben. Die interne Länge des Puffers spielt keine Rolle. Ist das Argument null, wird eine NullPointerException ausgelöst.


Beispiel Beispiel Vergleiche einen String mit einem StringBuffer:

String s = "Elektrisch-Zahnbürster"; 
StringBuffer sb = new StringBuffer( "Elektrisch-Zahnbürster" ); 
System.out.println( s.equals(sb) );                   // false 
System.out.println( s.equals(sb.toString()) );        // true 
System.out.println( s.contentEquals(sb) );            // true

equals() bei StringBuffer bzw. StringBuilder?

Wollen wir zwei StringBuffer- bzw. StringBuilder-Objekte miteinander vergleichen, werden wir noch mehr enttäuscht. Die Klassen deklarieren überhaupt keine eigene equals()-Methode. Es gibt zwar die übliche von Object geerbte Methode, doch das heißt, nur Objektreferenzen werden verglichen. Wenn also zwei verschiedene StringBuffer/StringBuilder-Objekte mit gleichem Inhalt mit equals() verglichen werden, kommt trotzdem immer false heraus.


Beispiel Beispiel Um den inhaltlichen Vergleich von zwei StringBuffer-Objekten zu realisieren, müssen wir diese erst mit toString() in Strings umwandeln.

StringBuffer sb1 = new StringBuffer( "www.tutego.com" ); 
StringBuffer sb2 = new StringBuffer( "www.tutego.com" ); 
System.out.println( sb1.equals( sb2 ) );                        // false 
System.out.println( sb1.toString().equals( sb2.toString() ) );  // true 
System.out.println( sb1.toString().contentEquals( sb2 ) );      // true


Galileo Computing - Zum Seitenanfang

4.4.6 hashCode() bei StringBuffer/StringBuilder topZur vorigen Überschrift

Die obige Betrachtung zeigt, dass eine Methode equals(), die den Inhalt von StringBuffer/StringBuilder-Objekten vergleicht, nicht schlecht wäre. Dennoch besteht das Problem, wann StringBuffer/StringBuilder-Objekte als gleich angesehen werden sollen. Das ist interessant, denn StringBuffer/StringBuilder-Objekte sind nicht nur durch ihren Inhalt bestimmt, sondern auch durch die Größe ihres internen Puffers, ihre Kapazität. Sollte equals() den Rückgabewert true haben, wenn die Inhalte gleich sind oder nur, wenn Inhalt und Puffergröße gleich sind? Da jeder Entwickler andere Ansichten über die Gleichheit besitzt, bleibt es bei dem standardmäßigen Test auf identische Objektreferenzen.

Eine ähnliche Argumentation gilt bei der hashCode()-Methode, die für alle inhaltsgleichen Objekte denselben, im Idealfall eindeutigen Zahlenwert liefert. Die Klasse String besitzt eine hashCode()-Methode, doch StringBuffer/StringBuilder erbt die Implementierung aus der Klasse Object unverändert. Mit anderen Worten: Die Klassen selbst bieten keine Implementierung an.



Ihr Kommentar

Wie hat Ihnen das <openbook> gefallen? Wir freuen uns immer über Ihre freundlichen und kritischen Rückmeldungen.






<< zurück



Copyright © Galileo Press 2008
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


[Galileo Computing]

Galileo Press, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, info@galileo-press.de